svg-path-simplify 0.0.4 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +193 -11
- package/dist/svg-path-simplify.esm.js +241 -130
- package/dist/svg-path-simplify.esm.min.js +1 -1
- package/dist/svg-path-simplify.js +4068 -3958
- package/dist/svg-path-simplify.min.js +1 -1
- package/dist/svg-path-simplify.node.js +240 -130
- package/dist/svg-path-simplify.node.min.js +1 -1
- package/index.html +6 -1
- package/package.json +2 -1
- package/src/detect_input.js +2 -0
- package/src/index.js +4 -4
- package/src/pathData_simplify_cubic_extrapolate.js +6 -3
- package/src/pathSimplify-main.js +120 -64
- package/src/svgii/pathData_convert.js +7 -3
- package/src/svgii/pathData_remove_collinear.js +10 -2
- package/src/svgii/pathData_remove_zerolength.js +16 -0
- package/src/svgii/pathData_reorder.js +9 -4
- package/src/svgii/pathData_split.js +4 -0
- package/src/svgii/pathData_toPolygon.js +98 -47
- package/src/svgii/poly_analyze.js +20 -16
- package/src/svgii/svg_cleanup.js +10 -1
- package/test.js +14 -0
- /package/src/svgii/{simplify_polygon.js → polygon_unite.js} +0 -0
package/README.md
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/svg-path-simplify)
|
|
2
|
+
[](https://www.npmjs.com/package/svg-path-simplify)
|
|
3
|
+
[](https://cdn.jsdelivr.net/npm/svg-path-simplify@latest/dist/svg-path-simplify.min.js)
|
|
4
|
+
[](https://www.unpkg.com/svg-path-simplify@latest/dist/svg-path-simplify.js)
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
# svg-path-simplify
|
|
2
8
|
Simplify Bézier paths while keeping shape.
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
This library prioritizes **visual quality** over numeric compression gains.
|
|
10
|
+
## *Watch the curve, not the file size!*
|
|
11
|
+
While this library reduces SVG markup sizes significantly by removing commands it prioritizes **visual quality** over numeric compression gains.
|
|
7
12
|
Unlike most existing approaches (e.g in graphic applications), it checks where simplifications are suitable and stops simplification at the right »point« (literally).
|
|
8
13
|
|
|
14
|
+

|
|
15
|
+
*Fira Sans (based on truetype/glyph quadratic commands) converted to cubic Bèziers. Right:Original; Left:optimized*
|
|
9
16
|
|
|
10
17
|
## Features – what it does
|
|
11
18
|
* reduces the number of SVG commands (both Bèziers and lines) by converting/combining adjacent:
|
|
@@ -13,7 +20,7 @@ Unlike most existing approaches (e.g in graphic applications), it checks where s
|
|
|
13
20
|
* flat Béziers to Linetos
|
|
14
21
|
* colinear lines (`L`)
|
|
15
22
|
|
|
16
|
-
* reorders path starting points to
|
|
23
|
+
* reorders path starting points to replace unnecessary closing linetos by `Z` commands
|
|
17
24
|
* optimizes SVG file size by contextually converting to:
|
|
18
25
|
* shorthand commands (`C` => `S`, `Q` => `T`, `L`=>`H` or `V`)
|
|
19
26
|
* cubics to quadratic Béziers (only 1 control point)
|
|
@@ -21,19 +28,22 @@ Unlike most existing approaches (e.g in graphic applications), it checks where s
|
|
|
21
28
|
|
|
22
29
|
* adaptive coordinate rounding: small or large details can be auto-detected to find a suitable floating point accuracy without guessing the decimal value (3 decimals may not be the silver bullet=)
|
|
23
30
|
* split segments at extremes – only useful for manual editing
|
|
31
|
+
* optimize either path data strings or SVG markup code
|
|
32
|
+
|
|
33
|
+
### Limitations: What it's not
|
|
34
|
+
This lib's focus is on path data optimizations. While it also provides some basic cleanup options for entire SVG documents (e.g removal of hidden elements or path merging) – if you need a full blown document optimization better opt for [SVGO](https://github.com/svg/svgo).
|
|
24
35
|
|
|
25
36
|
|
|
26
37
|
## Usage
|
|
27
38
|
|
|
28
|
-
### Browser
|
|
39
|
+
### Browser
|
|
29
40
|
|
|
41
|
+
#### Example 1: parse and simplify (using defaults)
|
|
30
42
|
```html
|
|
31
43
|
<script src="https://cdn.jsdelivr.net/npm/svg-path-simplify@latest/dist/svg-path-simplify.min.js"></script>
|
|
32
44
|
```
|
|
33
45
|
|
|
34
46
|
```js
|
|
35
|
-
|
|
36
|
-
// stringified pathData – 2 cubic Bézier commands
|
|
37
47
|
let pathDataString =
|
|
38
48
|
`
|
|
39
49
|
M 57.13 15.5
|
|
@@ -42,20 +52,192 @@ c 0.94 2.91 1.45 6.01 1.45 9.23
|
|
|
42
52
|
`
|
|
43
53
|
|
|
44
54
|
// try to simplify
|
|
45
|
-
let pathDataOpt = svgPathSimplify(pathDataString)
|
|
55
|
+
let pathDataOpt = svgPathSimplify(pathDataString);
|
|
46
56
|
|
|
47
|
-
|
|
57
|
+
// simplified pathData
|
|
58
|
+
console.log(pathDataOpt)
|
|
59
|
+
// returns `M 57.1 15.5c16.5 0 29.9 13.4 29.9 29.9`
|
|
60
|
+
```
|
|
48
61
|
|
|
62
|
+
#### ESM version
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
64
|
+
```js
|
|
65
|
+
import { svgPathSimplify } from '../dist/svg-path-simplify.esm.min.js'
|
|
52
66
|
|
|
67
|
+
let pathDataString =
|
|
68
|
+
`
|
|
69
|
+
M 57.13 15.5
|
|
70
|
+
c 13.28 0 24.53 8.67 28.42 20.65
|
|
71
|
+
c 0.94 2.91 1.45 6.01 1.45 9.23
|
|
72
|
+
`
|
|
73
|
+
|
|
74
|
+
// try to simplify
|
|
75
|
+
let pathDataOpt = svgPathSimplify(pathDataString);
|
|
76
|
+
|
|
77
|
+
// simplified pathData
|
|
78
|
+
console.log(pathDataOpt)
|
|
53
79
|
// returns `M 57.1 15.5c16.5 0 29.9 13.4 29.9 29.9`
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### node.js
|
|
83
|
+
Install module via npm:
|
|
84
|
+
```
|
|
85
|
+
npm install svg-path-simplify
|
|
86
|
+
```
|
|
87
|
+
Import:
|
|
88
|
+
```
|
|
89
|
+
import { svgPathSimplify } from 'svg-path-simplify';
|
|
90
|
+
|
|
91
|
+
// use it as in the above examples
|
|
92
|
+
let pathDataString = `M 57.13 15.5c 13.28 0 24.53 8.67 28.42 20.65c 0.94 2.91 1.45 6.01 1.45 9.23`;
|
|
93
|
+
let pathDataOpt = svgPathSimplify(pathDataString);
|
|
54
94
|
|
|
55
95
|
```
|
|
56
96
|
|
|
97
|
+
### API
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
let options = {}
|
|
101
|
+
let output = svgPathSimplify(input, options);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The first parameter is the SVG input:
|
|
105
|
+
* a path data string – as used in SVG `<path>` element's `d` attribute
|
|
106
|
+
* a polygon string – as used in SVG `<polygon>` element's `points` attribute
|
|
107
|
+
* an entire `<svg>` markup
|
|
108
|
+
|
|
109
|
+
While svg-path-simplify aims at a convenient config-free usage you can tweak the simplification and output via these options passed as an object.
|
|
110
|
+
|
|
111
|
+
| parameter | effect | type | default |
|
|
112
|
+
| -- | -- | -- | -- |
|
|
113
|
+
| simplifyBezier | main Bézier simplification. When disabled you get the common optimization similar to SVGO (rounding, to all relative and shorthand conversions) | Boolean | true |
|
|
114
|
+
| getObject | whether to return the SVG/pathdata markup directly or a detailed object (containing more info) | Boolean | true |
|
|
115
|
+
| tolerance | increase or decrease tolerance: higher values allow more distortions, lower ones more shape fidelity | Number | 1 |
|
|
116
|
+
| optimizeOrder | reorders commands to get more adjacent simplification candidates. Improves optimization efficiency | Boolean | true |
|
|
117
|
+
| removeColinear | removes unnecessary zero-length or colinear lineto commands | Boolean | true |
|
|
118
|
+
| flatBezierToLinetos | replaces flat Béziers with linetos which also can be stripped via previous colinear removal | Boolean | true |
|
|
119
|
+
| revertToQuadratics | replaces cubic Béziers with quadratic (more compact) ones when applicable | Boolean | true |
|
|
120
|
+
| keepExtremes | skips simplification accross x/y extrema – improves shape fidelity | Boolean | true |
|
|
121
|
+
| keepCorners | skips simplification corners – improves shape fidelity | Boolean | true |
|
|
122
|
+
| extrapolateDominant | tries to extrapolate adjacent curves based on dominant larger segment. Effective but adds computational load. Disable it for better performance | Boolean | true |
|
|
123
|
+
| keepInflections | retains commands introducing direction changes – adds complexity but may help for editing in a graphic application | Boolean | false |
|
|
124
|
+
| addExtremes | adds commands at x/y extrema – adds complexity but may help for editing in a graphic application | Boolean | false |
|
|
125
|
+
| autoAccuracy | calculates a suitable floating point precision for coordinate rounding. Usually rather conservative – decreasing by one decimal should work without significant distortions | Boolean | true |
|
|
126
|
+
| decimals | manual floating point rounding precision – overriden when `autoAccuracy` is enabled | Number | 3 |
|
|
127
|
+
| minifyD | path data microoptimization: removes recurring command type tokens, whitespace and leading zeroes: 0: maximum optimization; 1: "verbose" dont't omit command type tokes; 2: "beautify" separate each command with new lines (e.g for educational purposes) | Number | 0 |
|
|
128
|
+
| quadraticToCubic | converts all quadratic Béziers to cubics – recommended for efficiency | Boolean | true |
|
|
129
|
+
| toRelative | converts all commands to relative – reduces file size | Boolean | true |
|
|
130
|
+
| toShorthands | converts all commands to shorthand when applicable – reduces file size | Boolean | true |
|
|
131
|
+
| arcToCubic | converts elliptic arc `A` commands to cubic approximations – not recommended | Boolean | false |
|
|
132
|
+
| removeHidden | removes hidden elements for SVG inputs | Boolean | true |
|
|
133
|
+
| mergePaths | concatenates paths into single one – does not respect individual styles! | Boolean | false |
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### Example 2: Apply options
|
|
138
|
+
The following example would return a detailed object containing the stringified "normalized" pathdata (all absolute and "longhand" command notation).
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
let options = {
|
|
142
|
+
extrapolateDominant: false,
|
|
143
|
+
decimals: 3,
|
|
144
|
+
toRelative: false,
|
|
145
|
+
toShorthands = false,
|
|
146
|
+
minifyD: 2,
|
|
147
|
+
getObject: true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let input = `M717 208c-35 12-74 14-135 14 54 25 82 64 82 117 0 93-68 157-177 157-21 0-40-3-59-9-14 10-22 27-22 43 0 26 20 38 60 38h74c93 0 158 55 158 128 0 90-75 141-217 141-149 0-198-44-198-141h73c0 56 25 77 125 77 97 0 135-23 135-71 0-44-34-66-93-66h-73c-78 0-119-38-119-88 0-30 18-59 51-82-54-28-78-68-78-128 0-93 78-161 178-161 73 1 120-6 152-17 16-6 36-14 60-24zm-235 27c-61 0-96 41-96 103s36 105 98 105 97-39 97-106-33-102-99-102z`;
|
|
151
|
+
|
|
152
|
+
let simplified = svgPathSimplify(input, options);
|
|
153
|
+
let {svg, d, report} = simplified;
|
|
154
|
+
|
|
155
|
+
console.log(simplified)
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
// returns
|
|
159
|
+
{
|
|
160
|
+
"svg": "",
|
|
161
|
+
"d": "M 717 208
|
|
162
|
+
C 682 220 643 222 582 222
|
|
163
|
+
C 636 247 664 286 664 339
|
|
164
|
+
C 664 432 596 496 487 496
|
|
165
|
+
C 466 496 447 493 428 487
|
|
166
|
+
C 414 497 406 514 406 530
|
|
167
|
+
C 406 556 426 568 466 568
|
|
168
|
+
L 540 568
|
|
169
|
+
C 633 568 698 623 698 696
|
|
170
|
+
C 698 786 623 837 481 837
|
|
171
|
+
C 332 837 283 793 283 696
|
|
172
|
+
L 356 696
|
|
173
|
+
C 356 752 381 773 481 773
|
|
174
|
+
C 578 773 616 750 616 702
|
|
175
|
+
C 616 658 582 636 523 636
|
|
176
|
+
L 450 636
|
|
177
|
+
C 372 636 331 598 331 548
|
|
178
|
+
C 331 518 349 489 382 466
|
|
179
|
+
C 328 438 304 398 304 338
|
|
180
|
+
C 304 245 382 177 482 177
|
|
181
|
+
C 555 178 602 171 634 160
|
|
182
|
+
C 650 154 670 146 694 136
|
|
183
|
+
Z
|
|
184
|
+
M 482 235
|
|
185
|
+
C 421 235 386 276 386 338
|
|
186
|
+
C 386 400 422 443 484 443
|
|
187
|
+
C 546 443 581 404 581 337
|
|
188
|
+
C 581 270 548 235 482 235
|
|
189
|
+
Z
|
|
190
|
+
",
|
|
191
|
+
"report": {
|
|
192
|
+
"original": 29,
|
|
193
|
+
"new": 29,
|
|
194
|
+
"saved": 0,
|
|
195
|
+
"compression": 148.46,
|
|
196
|
+
"decimals": 0
|
|
197
|
+
},
|
|
198
|
+
"inputType": "pathDataString",
|
|
199
|
+
"mode": 0
|
|
200
|
+
}
|
|
201
|
+
*/
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Demos
|
|
205
|
+
You can easily test this library via the [simplify webapp](https://herrstrietzel.github.io/svg-path-simplify/) or by checking the demo folder.
|
|
206
|
+
|
|
207
|
+
* [simple setup IIFE](./demo/simple-iife.html)
|
|
208
|
+
* [simple setup esm](./demo/simple-esm.html)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
## Changelog, Updates and rollback
|
|
212
|
+
### Changelog
|
|
213
|
+
... not much to say at this point
|
|
214
|
+
|
|
215
|
+
### Rollback
|
|
216
|
+
If you encounter any issues with the recent versions you can rollback to a previous version.
|
|
217
|
+
See all versions on
|
|
218
|
+
* [npm](https://www.npmjs.com/package/svg-path-simplify)
|
|
219
|
+
* [jsdelivr](https://www.jsdelivr.com/package/npm/svg-path-simplify)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## Bug reporting
|
|
223
|
+
If you found a bug - feel free to file an [issue](https://github.com/herrstrietzel/svg-path-simplify/issues).
|
|
224
|
+
For debugging you may also test your example in the [webapp](https://herrstrietzel.github.io/svg-path-simplify).
|
|
225
|
+
You can also post in the [discussions](https://github.com/herrstrietzel/svg-path-simplify/discussions/) if you have ideas for missing features.
|
|
226
|
+
|
|
57
227
|
|
|
228
|
+
## Related libraries
|
|
229
|
+
* **polygon simplification:** Volodymyr Agafonkin for [»simplify.js«](https://github.com/mourner/simplify-js)
|
|
230
|
+
* **polygon smoothing/curve fitting** [simplify.js](http://paperjs.org/reference/path/#simplify)
|
|
58
231
|
|
|
232
|
+
## Other SVG related projects
|
|
233
|
+
* [poly-simplify](https://github.com/herrstrietzel/poly-simplify): Simplify/reduce polylines/polygon vertices in JS
|
|
234
|
+
* [svg-getpointatlength](https://github.com/herrstrietzel/svg-getpointatlength): Calculate path lengths, points or angles at lengths based on raw pathdata
|
|
235
|
+
* [fix-path-directions](https://github.com/herrstrietzel/fix-path-directions): Correct sub path directions in compound path for apps that don't support fill-rules
|
|
236
|
+
* [svg-pathdata-getbbox](https://github.com/herrstrietzel/svg-pathdata-getbbox): Calculate a path bounding box based on its pathdata
|
|
59
237
|
|
|
60
238
|
|
|
239
|
+
## Credits
|
|
240
|
+
* [Vitaly Puzrin](https://github.com/puzrin) for [svgpath library](https://github.com/fontello/svgpath) providing for instance a great and customizable [arc-to-cubic approximation](https://github.com/fontello/svgpath/blob/master/lib/a2c.js) – the base for the more accurate arc-to-cubic approximations
|
|
241
|
+
* [Jarek Foksa](https://github.com/jarek-foksa) for developping the great [getPathData() polyfill](https://github.com/jarek-foksa/path-data-polyfill) – probably the most productive contributor to the ["new" W3C SVGPathData interface draft](https://svgwg.org/specs/paths/#InterfaceSVGPathData)
|
|
242
|
+
* obviously, [Dmitry Baranovskiy](https://github.com/dmitrybaranovskiy) – a lot of these helper functions originate either from Raphaël or snap.svg – or are at least heavily inspired by some helpers from these libraries
|
|
61
243
|
|