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 CHANGED
@@ -1,11 +1,18 @@
1
+ [![npm version](https://img.shields.io/npm/v/svg-path-simplify)](https://www.npmjs.com/package/svg-path-simplify)
2
+ [![license](https://img.shields.io/npm/l/svg-path-simplify)](https://www.npmjs.com/package/svg-path-simplify)
3
+ [![CDN](https://img.shields.io/badge/CDN-jsDelivr-E84D3D?style=flat)](https://cdn.jsdelivr.net/npm/svg-path-simplify@latest/dist/svg-path-simplify.min.js)
4
+ [![CDN](https://img.shields.io/badge/CDN-unpkg-blue?style=flat)](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
- > Darling, please look at the graphic not the file size
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
+ ![simplification](./demo/img/splash.png)
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 strip unnecessary closing lineto commands
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 IIFE
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
- let { d, pathData, report } = pathDataOpt;
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
- // simplified pathData
51
- console.log(d)
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