This project started as fork of svgpath.
They are very similar, but I rewrote a big part of the library to fit my needs. Why ? Because I need a less strict parser (if some error is present in the path I don't want the parser to stops.), more options to convert the path back to string and some functionality that the authors of svgpath don't want (like .inbox
). I also want to use this library in a browser (not only in node).
Low level toolkit for SVG paths transformations. Sometime you can't use
transform
attributes and have to apply changes to svg paths directly. Then this package is for you :) !
Note, this package works with paths
, not with svg xml sources.
var SVGPath = require('svgpath');
<script src="svgpathy.js" type="text/javascript" ></script>
var transformed = SVGPath(__your_path__)
.scale(0.5)
.translate(100,200)
.rel()
.round(1)
.toString();
Almost all methods are chainable (return self).
Constructor. Creates new SVGPath
class instance with chainable methods.
The new
can be omitted.
Create a copy of the path.
Rescale path (the same as SVG scale
transformation). sy
= sx
by default.
Translate path (the same as SVG translate
transformation). y
= 0 by default.
Rotate path to angle
degree around (rx, ry) point. If rotation center not set,
(0, 0) used. The same as SVG rotate
transformation.
Skew the X-coordinate according to a certain angle specified in degrees. The same as SVG skewX
transformation.
Skew the Y-coordinate according to a certain angle specified in degrees. The same as SVG skewY
transformation.
Apply 2x3 affine transform matrix to path. Params - array. The same as SVG
matrix
transformation.
Any SVG transform or their combination. For example rotate(90) scale(2,3)
.
The same format, as described in SVG standard for transform
attribute.
This command translate and scale the path to put it in a box. The way to put the path in the box is controlled by the same type of parameters as in PreserveAspectRatio.
Example .inbox('10 -10 200 400 slice xMinYMid')
or .inbox(10, -10, 200, 400, 'slice xMinYMid')
translate and scale the path by respecting its aspect ratio and by covering the rectangle with size 200x400 starting at (10,-10).
The possible parameters are :
meet
(the default) : scale the path (aspect ratio is preserved) as much as possible to fit the entire path in the box.slice
: scale the path (aspect ratio is preserved) as less as possible to cover the box.fit
(=none
) : scale the path (aspect ratio is not preserved) to fit the box.move
: translate only (no scale) the path according toxM..YM..
parameter.
Converts all path commands to absolute.
Converts all path commands to relative. Useful to reduce output size.
Converts smooth curves T
/t
/S
/s
with "missed" control point to
generic curves (Q
/q
/C
/c
).
Replaces all arcs with bezier curves.
Reverse the path. Before to do this it execute .unshort()
because it is not clear what is the reverse of T
/t
/S
/s
.
Round all coordinates to given decimal precision. By default round to integer.
Useful to reduce resulting output string size.
When called not only the coordinates are rounded but the path .precision
is set to the corresponding value.
This command normalize the path using the following rules:
- The path must starts with
M
. So the firstm
is converted toM
: yes ifF
(default) is present, no iff
is present in flags string. - Repeated
M
andm
are smashed to one : yes ifM
(default) is present, no ifm
is present in flags string. - Repeated
Z
andz
are smashed to one : yes ifZ
(default) is present, no ifz
is present in flags string. - Empty segments (like
l 0 0
) are removed or converted to line segment if followed byS
,s
,T
,t
,: yes ifE
(default) is present, no ife
is present in flags string. - Arcs:
- Are converted to line segments if one of the radii is 0 (up to the precision) : yes if
L
(default) is present, no ifl
is present in flags string. - The elliptic part (controlled by the flags
E
ande
)- If the radii are too small, they are scaled.
- The radii are set to positive numbers.
- The angles is set to be in
[0,90[
.
- Set the flags to
0
or1
(this is normally done already by the parser) : yes ifG
is present, no ifg
(default) is present in flags string.
- Are converted to line segments if one of the radii is 0 (up to the precision) : yes if
Example: .normalize('leg')
will normalize the path without normalizing the arc segments.
These methods evaluate the affine transform (if any) at their beginning.
Returns final path string. The output is controlled by multiple parameters.
parameters
(string) set the number format and the 'zip' level.- number format : for example
00.0XXX
state that the numbers has to have at least to digits before the dot and one after, and that the precision is 4. For example 1.00004 will be printed as 1.0 and 1.00005 will be printed as 1.0001. - the coordinate separator : if
,
is present the coordinates will be separated by a comma. The spaces around the,
(if any) meters. - All the following zip parameters are turned on or off by a '+/-' flag :
+
= turn zip on (default),-
turn the zip off. - zip space before commands : yes if
B
(default) is present, no ifb
is present. - zip space after commands (Z is particular case) : yes if
A
(default) is present, no ifa
is present. - zip space after Z or z command : yes if
Z
(default) is present, no ifz
is present. - zip space before
-
sign (negative numbers) : yes ifM
(default) is present, no ifm
is present. - zip space before
.
sign (numbers starting with dot) : yes ifD
is present, no ifd
(default) is present. - zip the size of the numbers by using scientific notation like
1e4
: yes ifE
is present, no ife
(default) is present. - remove repeated commands : yes if
R
(default) is present, no ifr
is present. - remove
L
commands afterM
: yes ifL
is present, no ifl
(default) is present.
- number format : for example
parameters
(boolean) :true
is equivalent to'+'
(turn on all zip parameters),false
is equivalent to'-'
(turn off all zip parameters).normalize
(boolean) if true the path is normalised with.normalize()
.errstop
(boolean) if true only the segments before the first error are returned.
examples :
.toString('.XXXX DEL')
or.toString('.XXXX +')
to obtain the shortest output with precision 4..toString('0.X, -')
to obtain the nice output with coma followed by space as coordinate separator. The precision is set to 1, and there will be at least one digit in the integer part..toString('0.00XX,-RL')
another nice output with removed repeats. The precision is set to 4, and the numbers will be with at least 3 digits (one before the dot and two after).
errstop
(boolean) if true only the segments before the first error are returned.
Apply the affine transform and concatenate all segments to one array like ['M', 0, 0, 'L', 1, 1]
. This array can be joined .toArray().join(' ')
to produce a valid SVG string in faster way than .toString()
.
Returns the minimal rectangle that contains the path as Box
object.
This Box
object has the following members / methods:
.minX
.maxX
.minY
.maxY
.width()
.height()
.toArray()
-> [minX, minY, maxX, maxY].inboxMatrix(parameters)
->M
affine transform matrix that can be used with.matrix(M)
. The parameters are the same as.inbox(parameters)
.
Apply the affine transforms. This method is called by default by the output methods .toString()
and .toBox()
Apply iterator to all path segments.
- Each iterator receives
segment
,index
,x
andy
parameters. Where (x, y) are the absolute coordinates of segment start point. Thethis
inside the iterator is the SVGPath object. - Iterator can modify current segment directly (return nothing in this case).
- Iterator can return array of new segments to replace current one (
[]
means that current segment should be deleted).
Return true if the path has parse errors.
Return a string with one error per line. Every error line contain the position and the segment number where the error has been found. An example of error is :
[pos:14, seg:4] Non expected character [R]. I'll ignore it.
.segments
: an array of arrays that contains the path segments. Something like[['M', 10, 0], ['L', 10, 0]]
for example..affineTransform
: an object of class AffineTransform that represent the transform to apply to the path. At the beginning this transform is the identity. Every time we use one of the methods.scale()
,.translate()
, ... we modify this object. We actually apply this transform to the path with.doTransform()
(and after that it is reset to identity). We can transform this object to an array with.toArray()
method..errs
: is an array of strings containing the parse errors of the initial path string. Every error is an object with three fields:position
: the position in the path string where the error was found;segment
: the segment number where the error is;message
: the message of the error;
.precision
(integer, default 15) This value is set by.round()
,.toSting()
,.toBox()
. It is used not only to round the coordinates but also by.normalize()
.
This parameters control the default behaviour of .toString()
. They are overwritten by the 'parameters' argument of .toString(parameters)
.
.leading_zeros
(integer >=0, default 0).trailing_zeros
(integer >=0, default 0).coordinate_separator
(" " | "," | ", " | " , ", default : " ").zip_space_before_command
(default true).zip_space_after_comand
(default true).zip_space_afterz
(default true).zip_space_before_minus
(default true).zip_space_before_dot
(default false).zip_space_use_e
(default false).zip_remove_repeats
(default true).zip_remove_l_after_m
(default false)
This parameters control the default behaviour of .normalize()
. They are overwritten by the 'flags' argument of .normalize(flags)
.
.normalize_first_m
(default true) : Change first m to M ?.normalize_remove_empty
(default true) : Remove empty segments ? Never remove Mm and before SsTt..normalize_smash_m
(default true) : Smash multiple Mm to one ?.normalize_smash_z
(default true) : Smash multiple Zz to one ?.normalize_a2l
(default true) : Arc with zero radii to line ?.normalize_arc_ellipse
(default true) : Scale up radii and set the angle in [0,90[.normalize_arc_flags
(default false) : Set arc flags to 0 or 1 (normally already done by the parser)
-
The library is located in the
lib
folder. -
The browser version
svgpathy.js
is generated using esbuild by the command :esbuild --outfile=svgpathy.js --bundle browserify_svgpath.js
-
In a browser you can use a CDN version :
<script src="https://cdn.jsdelivr.net/gh/kpym/SVGPathy@master/lib/svgpathy.min.js" type="text/javascript" ></script>
- Add parameters to
unshort
that allow to replaceH|h|V|v
byL|l
, andZ|z
byL+Z+M|l+z+m
. - Add
short
method that replace when possibleC|c
byS|s
,Q|q
byT|T
,L|l
byH|h|V|v
,L+Z+M|l+z+m
byZ|z
(multipleM|m
to single one is already implemented innormalise
). - In transform method add the possibility to have
indox
in the string parameter. - Add advanced mode in the Playground where we can enter a string like ".normalise().rotate(30).toString()" to execute over each path. MIT