I have an SVG path like this:
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" version="1.1" baseProfile="full">
<path d="M47.16,66.38c0.62,1.65-0.03,2.93-0.92,4.28c-5.17,7.8-8.02,11.38-14.99,18.84c-2.11,2.25-1.5,4.18,2,3.75c7.35-0.91,28.19-5.83,40.16-7.95" style="fill:none;stroke:black;stroke-width:2" />
</svg>
I can render the path but can't seem to find a way to make the path animate so that it looks like it is "being draw" as if with pencil. The animate node works for single coords but not for paths.
I will eventually end up using this animation in an iPhone app either with a parser or with a UIWebView.
Try animating the 'stroke-dashoffset' (note that you need a matching 'stroke-dasharray' with it), see this example. The length of the path that needs to be computed to be able to use this successfully can be fetched via script like:
var pathlength = yourPathElm.getTotalLength()
View source on the example to see how it's done.
I tried for a long while to do this without having to add extra scripts to the header (that I have no idea of javascript didn't help), so here's the solution:
<path d="..." stroke-dasharray="">
<animate attributeName="stroke-dashoffset" from="" to="0" dur="1s" begin="0s"
onload="var length = parentNode.getTotalLength();
parentNode.setAttribute('stroke-dasharray',length+','+length);
this.setAttribute('from',length)" />
</path>
I added extra line breaks for readability here.
This is legal in SVG (although not in HTML) because the svg:animate element allows onload, which most HTML elements do not.
Once you've rendered your SVG path, to make it look like it's being drawn with a pencil, you could simply cover it all with an opaque layer, and then animate the movement of this layer along the path.
To find the CGPath along which you'll move the layer you can use this library:
https://github.com/arielelkin/PocketSVG
This will parse the SVG data into a UIBezierPath. Then:
SvgToBezier *myBezier = [[SvgToBezier alloc] initFromSVGPathNodeDAttr:#"M176.17,369.617c0,0,335.106-189.361,214.894,38.298s129.787,282.978,178.723,42.553C618.724,210.042,834.681,87.702,790,307.915" rect:CGRectMake(0,0,1024,768)];
UIBezierPath *myPath = myBezier.bezier;
CAKeyframeAnimation *mySVGPathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
bounceAnimLeft.duration = 3;
bounceAnimLeft.path = myPath.CGPath;
[myObjectToMove.layer addAnimation:mySVGPathAnimation forKey:#"pathAnimation"];
Related
i need to convert UIBezierPath to SVG.
my UIBezierPath internally has collection cubic bezier paths as subpaths.
these subpaths when taken together forms a closed path, meaning, the last cubic-bezier's endpoint is same as first cubic-bezier's startpoint.
when i draw this path on a CAShapeLayer with some fill color, the overall path is filled with given color correctly.
now, I need to simulate the same behavior in SVG ( which is loaded inside a webview ), problem is the sub-paths are independent in svg and i can't combine them (group them) into a single path, so we lose the contextual information that this collection of paths are closed and hence fail to fill.
i tried to put these svg cubic-beizer path inside g element , that didnt work either. like below
<g>
<path d="M1013.3,1228.7 C1007.1,1238.4 991.4,1242.6 984.2,1242.6" />
<path d="M984.2,1233.6 C995.1,1237.3 1008.3,1231.7 1013.2,1231.7" />
<path d="M1013.2,1221.3 C1018.0,1210.9 1013.8,1197.1 1004.0,1197.1" />
</g>
how do i solve this problem ? any inputs are appreciated.
Thanks,
I'm not sure to understand, but you can use as many beziers path as you want in the same curve. Here is a way: http://jsfiddle.net/74os2um3/
Just put it in one <path> and add a Z to close it.
<path d="M1013.3,1228.7 C1007.1,1238.4 991.4,1242.6 984.2,1242.6 L984.2,1233.6 C995.1,1237.3 1008.3,1231.7 1013.2,1231.7 L1013.2,1221.3 C1018.0,1210.9 1013.8,1197.1 1004.0,1197.1 Z" />
I write an svg parser.
I have an svg file with the following string:
<polygon fill="#969696" stroke="#323232" stroke-width="0.5" stroke-miterlimit="10" points="555.583,394.805 564.085,394.805 564.02,394.817 568.896,399.655"/>
And this picture looks different in various applications. Possible cases:
1)linejoin = bevel
2)linejoin = miter (Corel Draw)
3)two nearest points are not connected (Inkscape, adobe illustrator)
The second and the third case look look like:
It seems that svg documentation advices to draw the same picture as corel draw draws (right picture). But it is not very pretty.
So what rule will allow to achieve the left picture?
You seem to have a bogus co-ordinate in your polygon. The polygon has 3 vertices but you're supplying 4 and the bogus one is confusing things. Try this instead...
<polygon fill="#969696" stroke="#323232" stroke-width="0.5" stroke-miterlimit="10" points="555.583,394.805 564.085,394.805 568.896,399.655"/>
Correct me if I'm wrong but I could have sworn chart.chartWidth used to return the exact width attribute as returned by getSVG().
I'll explain.
Say I target a div that forces a chart to render with the following as read via view source.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="270" height="300">
Now if I call chart.highcharts().chartWidth I'll get 270. Great!
But if I then call chart.highcharts().getSVG() I'll get this is an opening
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="600">
I've been using and adding to an export function that will combine multiple charts into a single and I typically need to do some scaling to get it to look nice. The scale is dependent on the originally rendered size, not the default and now it's causing a huge problem.
Shouldn't getSVG return svg representing the chart as it appears in html?
Have you tried sourceWidth or scale parameter?
I need to fill a path which is created dynamically using javascript. I've created a gradient for that and used that to fill my path, but nothing happened. What's wrong with my code?
$('svg').prepend('<defs id="gradient"></defs>');
$('#gradient').append('<linearGradient id="yellow" x1="0%" y1="0%" x2="100%" y2="0%"> </linearGradient>');
$('#yellow').append('<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" /> <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />');
$('g:nth-child(2n+1) path').attr('fill','url(#gradient)');`
Your fill points to a defs element and not the linearGradient. The id="gradient" should be on the linearGradient element - or alternatively make the fill url(#yellow)
I'm trying to draw a label on a polygon of an svg file. The problem I'm facing is to find out roughly the center of this polygon to place the label, as the path's coordinates are in svg format and need to be parsed. Is there an easier way to determine the center of an svg polygon (maybe someone can point out a javascript library or a snippet)? I'm using Raphael javascript library to manipulate the svg, but it doesn't seem to go beyond the standard svg functionality.
You could try the following approximation for doing something similar to the polygon suggestion, based on SVG DOM methods:
var totalPathLength = pathelm.getTotalLength();
var step = totalPathLength / 100;
for(var dist=0; dist < totalPathLength; dist+=step)
{
var pt = pathelm.getPointAtLength(dist);
addToAverage(pt.x, pt.y);
}
I think the simplest approach is to use the center of the path element's boundingbox (pathelm.getBBox()), that's simpler than the polygon suggestion.
The simplest thing you could try doing is to calculate the center by taking the average of all the points in the polygon. It should work for all but the most irregular of polygons. I've used the same algorithm to good effect in my programs.
Best of luck.
Insert a text tag inside the svg and position it by calculating the width and hight
<svg width="447pt" height="559pt" viewBox="0 0 894 1118" version="1.1" xmlns="http://www.w3.org/2000/svg">
............
............
<text x="450" y="300" font-family="Verdana" font-size="15" fill="red" >
Text To Show
</text>
</svg>