I made a little Javascript library to quickly get info on an SVG path element. Check it out:
github | website. |
How To
The available methods are getJSON()
, getCommands()
, getCommandsArray()
, getSubPaths(deep)
, getRelativePath()
, getAbsolutePath()
and getGlobalCubicBezier()
.
Once you’ve included the script in your page, here’s how you start using them:
Begin
First, create a new SVGPathInfo
object.
You can pass it a handle to a path element:
var path_elem = document.getElementById('mypath');
var info1 = new SVGPathInfo(path_elem);
Or you can pass it a path string:
var path_string = "M0 0 L0 50L50 50M0 200L200 0";
var info2 = new SVGPathInfo(path_string);
Now you have access to a bunch of SVGPathInfo’s methods:
getJSON()
var path_json = info2.getJSON();
will output
{
"0":{
"type":"M",
"string":"M0 0",
"x":"0",
"y":"0"
},
"1":{
"type":"L",
"string":"L0 50",
"x":"0",
"y":"50"
},
"2":{
"type":"L",
"string":"L50 50",
"x":"50",
"y":"50"
}
"3":{
"type":"M",
"string":"M0 200",
"x":"0",
"y":"200"
},
"4":{
"type":"L",
"string":"L200 0",
"x":"200",
"y":"0"
}
}
getCommands()
var path_commands = info2.getCommands();
This will return the object that is described by the above JSON string.
getCommandsArray()
var path_commands = info2.getCommandsArray();
This returns an array of command strings, rather than an object of command objects:
["M0 0", "L0 50", "L50 50", "M0 200", "L200 0"]
getSubPaths(deep)
var subpaths = info2.getSubPaths(true);
//OR
var subpaths = info2.getSubPaths(); //default: false
This breaks down the path into subpaths, breaking wherever a moveto (M
/m
) command occurs.
The argument deep
is by default false
. If deep
is false
, it returns an array of subpath strings:
["M0 0L0 50L50 50", "M0 200L200 0"]
If deep
is true
, it returns an array of subpath arrays:
[["M0 0","L0 50","L50 50"], ["M0 200","L200 0"]]
getAbsolutePath()
var abs_path = info2.getAbsolutePath();
Wherever the lowercase form of a command is used, the coordinates that follow the command are relative – their location is specified relative to location of the pen, and not specified absolutely i.e. relative to the point of origin of the svg element (the top left corner).
This function converts the path to the absolute form and returns a string. (Note: my example path is already absolute.)
getRelativePath()
var rel_path = info2.getRelativePath();
This does the opposite of getAbsolutePath() – all absolute commands are modified so as to be specified in relation to the location of the pen.
"m0 0 l0 50 l50 0 m-50 150 l200 -200"
getGlobalCubicBezier()
var gcb_path = info2.getGlobalCubicBezier();
This function converts each command to a cubic Bézier and returns a string.
"M0 0C0 0 0 50 0 50C0 50 50 50 50 50M0 200C0 200 200 0 200 0"
Notes:
Accuracy
There is approximation involved, as is the nature of dealing with Bézier curves, and of course Javascript does famously imprecise maths. However, the result is quite good:
This svg image is the result of generating path strings using SVGPathInfo’s various functions, and assigning the resultant strings to the “d” attribute of path elements. I made the stroke-width of the paths decrease progressively so that all the paths can be seen at once. Here is the JS:
var info = new SVGPathInfo(path1);
document.getElementById('path2').setAttribute("d", info.getRelativePath());
document.getElementById('path3').setAttribute("d", info.getAbsolutePath());
document.getElementById('path4').setAttribute("d", info.getGlobalCubicBezier());
where
path1
has the original path (orange withstroke-width='30'
)path2
has the relative path (grey withstroke-width='18'
)path3
has the absolute path (pink withstroke-width='10'
)path4
has the cubic Bézier path (yellow withstroke-width='3'
)
Validitity
This library does not check the path’s validity. It will likely throw an error or behave unexpectedly if it is provided with an invalid path.
To Do
I have not yet implemented a conversion from the arc command (A
,a
) to cubic Bézier.