svg-path-simplify 0.2.6 → 0.3.0
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 +80 -5
- package/dist/svg-path-simplify.esm.js +465 -392
- package/dist/svg-path-simplify.esm.min.js +6 -6
- package/dist/svg-path-simplify.js +465 -392
- package/dist/svg-path-simplify.min.js +6 -6
- package/dist/svg-path-simplify.pathdata.esm.js +5094 -0
- package/dist/svg-path-simplify.pathdata.esm.min.js +9 -0
- package/dist/svg-path-simplify.poly.cjs +10 -1
- package/dist/svg-path-simplify.worker.js +27 -0
- package/dist/svg-path-simplify.worker.polyfills.js +32 -0
- package/index.html +90 -17
- package/package.json +3 -2
- package/src/index-pathdata.js +6 -0
- package/src/index-poly.js +9 -1
- package/src/index-worker.js +17 -0
- package/src/index.js +4 -1
- package/src/pathData_simplify_cubic_extrapolate.js +3 -2
- package/src/pathSimplify-main.js +54 -72
- package/src/pathSimplify-only-pathdata.js +274 -0
- package/src/svgii/geometry.js +48 -4
- package/src/svgii/pathData_analyze.js +8 -6
- package/src/svgii/pathData_convert.js +1 -1
- package/src/svgii/pathData_fix_directions.js +83 -0
- package/src/svgii/pathData_line_to_cubic.js +21 -0
- package/src/svgii/pathData_parse_els.js +7 -2
- package/src/svgii/pathData_remove_zerolength.js +0 -1
- package/src/svgii/pathData_reverse.js +0 -1
- package/src/svgii/pathData_toPolygon.js +61 -12
- package/src/svgii/rounding.js +2 -0
- package/src/svgii/svg-styles-to-attributes-const.js +2 -0
- package/src/svgii/svg_cleanup.js +92 -15
- package/tests/testSVG2.js +55 -0
- package/dist/svg-path-simplify.min.js.gz +0 -0
|
@@ -463,7 +463,7 @@ export function pathDataToShorthands(pathData, decimals = -1, test = false) {
|
|
|
463
463
|
let dy1 = (p0.y - cpPrev.y)
|
|
464
464
|
|
|
465
465
|
//adjust maxDist
|
|
466
|
-
maxDist = getDistManhattan(cpPrev, cpFirst) * 0.
|
|
466
|
+
maxDist = getDistManhattan(cpPrev, cpFirst) * 0.025
|
|
467
467
|
|
|
468
468
|
// reflected cp
|
|
469
469
|
let cpR = { x: cpPrev.x + dx1 * 2, y: cpPrev.y + dy1 * 2 }
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fix sub path directions
|
|
3
|
+
* pathdata must be be normalized to
|
|
4
|
+
* absolute and longhand commands
|
|
5
|
+
* toClockwise = force default direction
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { isPointInPolygon } from "./geometry";
|
|
9
|
+
import { getPolygonArea } from "./geometry_area";
|
|
10
|
+
import { getPolyBBox } from "./geometry_bbox";
|
|
11
|
+
import { reversePathData } from "./pathData_reverse";
|
|
12
|
+
import { getPathDataPolyPrecise } from "./pathData_toPolygon";
|
|
13
|
+
|
|
14
|
+
export function fixPathDataDirections(pathDataArr = [], toClockwise = false) {
|
|
15
|
+
|
|
16
|
+
let polys = []
|
|
17
|
+
|
|
18
|
+
pathDataArr.forEach((sub, i) => {
|
|
19
|
+
let pathData = sub.pathData
|
|
20
|
+
//console.log('sub', pathData);
|
|
21
|
+
let vertices = getPathDataPolyPrecise(pathData)
|
|
22
|
+
let area = getPolygonArea(vertices)
|
|
23
|
+
let isClockwise = area >= 0
|
|
24
|
+
polys.push({ pts: vertices, bb: getPolyBBox(vertices), cw: isClockwise, index: i, inter: 0, includes: [], includedIn: [] })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// check poly intersections
|
|
28
|
+
let l = polys.length;
|
|
29
|
+
for (let i = 0; i < l; i++) {
|
|
30
|
+
let prev = polys[i]
|
|
31
|
+
let bb0 = prev.bb
|
|
32
|
+
|
|
33
|
+
for (let j = 0; j < l; j++) {
|
|
34
|
+
|
|
35
|
+
let poly = polys[j]
|
|
36
|
+
let bb = poly.bb
|
|
37
|
+
|
|
38
|
+
// skip if the same poly or parent
|
|
39
|
+
if (i === j || poly.includes.includes(i)) continue
|
|
40
|
+
|
|
41
|
+
// if mid point is in previous polygon
|
|
42
|
+
let ptMid = { x: bb.left + bb.width / 2, y: bb.top + bb.height / 2 }
|
|
43
|
+
let inPoly = isPointInPolygon(ptMid, prev.pts, bb0)
|
|
44
|
+
|
|
45
|
+
if (inPoly) {
|
|
46
|
+
polys[j].inter += 1
|
|
47
|
+
poly.includedIn.push(i)
|
|
48
|
+
prev.includes.push(j)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// reverse paths
|
|
55
|
+
for (let i = 0; i < l; i++) {
|
|
56
|
+
|
|
57
|
+
let poly = polys[i]
|
|
58
|
+
let { cw, includedIn, includes } = poly
|
|
59
|
+
|
|
60
|
+
// outer path direction to counter clockwise
|
|
61
|
+
if (!includedIn.length && cw && !toClockwise
|
|
62
|
+
|| !includedIn.length && !cw && toClockwise
|
|
63
|
+
) {
|
|
64
|
+
pathDataArr[i].pathData = reversePathData(pathDataArr[i].pathData);
|
|
65
|
+
polys[i].cw = polys[i].cw ? false : true
|
|
66
|
+
cw = polys[i].cw
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// reverse inner sub paths
|
|
70
|
+
for (let j = 0; j < includes.length; j++) {
|
|
71
|
+
let ind = includes[j];
|
|
72
|
+
let child = polys[ind];
|
|
73
|
+
|
|
74
|
+
if (child.cw === cw) {
|
|
75
|
+
pathDataArr[ind].pathData = reversePathData(pathDataArr[ind].pathData);
|
|
76
|
+
polys[ind].cw = polys[ind].cw ? false : true
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return pathDataArr
|
|
82
|
+
|
|
83
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { interpolate } from "./geometry";
|
|
2
|
+
|
|
3
|
+
export function pathDataLineToCubic(pathData) {
|
|
4
|
+
|
|
5
|
+
for (let c = 1, l = pathData.length; c < l; c++) {
|
|
6
|
+
let com = pathData[c]
|
|
7
|
+
let { type, values, p0, cp1 = null, cp2 = null, p = null } = com;
|
|
8
|
+
if (type === 'L') {
|
|
9
|
+
|
|
10
|
+
let cp1 = interpolate(p0, p, 0.333)
|
|
11
|
+
let cp2 = interpolate(p, p0, 0.333)
|
|
12
|
+
|
|
13
|
+
pathData[c].type = 'C'
|
|
14
|
+
pathData[c].values = [cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y]
|
|
15
|
+
pathData[c].cp1 = cp1
|
|
16
|
+
pathData[c].cp2 = cp2
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return pathData
|
|
21
|
+
}
|
|
@@ -10,13 +10,18 @@ export function shapeElToPath(el) {
|
|
|
10
10
|
let d = pathData.map(com => { return `${com.type} ${com.values} ` }).join(' ')
|
|
11
11
|
let attributes = [...el.attributes].map(att => att.name);
|
|
12
12
|
|
|
13
|
+
//console.log(d);
|
|
14
|
+
//return []
|
|
15
|
+
|
|
13
16
|
let pathN = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
17
|
+
//let pathN = document.createElement('path');
|
|
14
18
|
pathN.setAttribute('d', d);
|
|
15
19
|
|
|
16
|
-
let exclude = ['x', 'y', 'cx', 'cy', 'dx', 'dy', 'r', 'rx', 'ry', 'width', 'height', 'points']
|
|
20
|
+
let exclude = ['x', 'y', 'x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'dx', 'dy', 'r', 'rx', 'ry', 'width', 'height', 'points'];
|
|
17
21
|
|
|
18
22
|
attributes.forEach(att => {
|
|
19
23
|
if (!exclude.includes(att)) {
|
|
24
|
+
//console.log(att, attributes, exclude);
|
|
20
25
|
let val = el.getAttribute(att);
|
|
21
26
|
pathN.setAttribute(att, val)
|
|
22
27
|
}
|
|
@@ -32,7 +37,7 @@ export function shapeElToPath(el) {
|
|
|
32
37
|
export function getPathDataFromEl(el, stringify = false) {
|
|
33
38
|
|
|
34
39
|
let pathData = [];
|
|
35
|
-
let type = el.nodeName;
|
|
40
|
+
let type = el.nodeName.toLowerCase();
|
|
36
41
|
let atts, attNames, d, x, y, width, height, r, rx, ry, cx, cy, x1, x2, y1, y2;
|
|
37
42
|
|
|
38
43
|
// convert relative or absolute units
|
|
@@ -4,6 +4,7 @@ import { simplifyRD } from "../simplify_poly_radial_distance";
|
|
|
4
4
|
import { getDistAv, getTatAngles, pointAtT } from "./geometry";
|
|
5
5
|
import { getPolyBBox } from "./geometry_bbox";
|
|
6
6
|
import { addDimensionData, analyzePathData } from "./pathData_analyze";
|
|
7
|
+
import { arcToBezier } from "./pathData_convert";
|
|
7
8
|
import { pathDataFromPoly } from "./pathData_fromPoly";
|
|
8
9
|
import { addExtremePoints } from "./pathData_split";
|
|
9
10
|
import { pathDataToD } from "./pathData_stringify";
|
|
@@ -12,13 +13,61 @@ import { getCurvePathData } from "./poly_to_pathdata";
|
|
|
12
13
|
import { renderPoint } from "./visualize";
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
export function getPathDataPolyPrecise(pathData = []) {
|
|
17
|
+
|
|
18
|
+
let poly = [];
|
|
19
|
+
for (let i = 0; i < pathData.length; i++) {
|
|
20
|
+
let com = pathData[i]
|
|
21
|
+
let prev = i > 0 ? pathData[i - 1] : pathData[i];
|
|
22
|
+
let { type, values } = com;
|
|
23
|
+
let p0 = { x: prev.values[prev.values.length - 2], y: prev.values[prev.values.length - 1] };
|
|
24
|
+
let p = values.length ? { x: values[values.length - 2], y: values[values.length - 1] } : ''
|
|
25
|
+
let cp1 = values.length ? { x: values[0], y: values[1] } : ''
|
|
26
|
+
|
|
27
|
+
switch (type) {
|
|
28
|
+
|
|
29
|
+
// convert to cubic to get polygon
|
|
30
|
+
case 'A':
|
|
31
|
+
if (typeof arcToBezier !== 'function') {
|
|
32
|
+
//console.log('has no arc to cubic conversion');
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
let cubic = arcToBezier(p0, values)
|
|
36
|
+
cubic.forEach(com => {
|
|
37
|
+
let vals = com.values
|
|
38
|
+
let cp1 = { x: vals[0], y: vals[1] }
|
|
39
|
+
let cp2 = { x: vals[2], y: vals[3] }
|
|
40
|
+
let p = { x: vals[4], y: vals[5] }
|
|
41
|
+
poly.push(cp1, cp2, p)
|
|
42
|
+
})
|
|
43
|
+
break;
|
|
44
|
+
|
|
45
|
+
case 'C':
|
|
46
|
+
let cp2 = { x: values[2], y: values[3] }
|
|
47
|
+
poly.push(cp1, cp2)
|
|
48
|
+
break;
|
|
49
|
+
case 'Q':
|
|
50
|
+
poly.push(cp1)
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// M and L commands
|
|
55
|
+
if (type.toLowerCase() !== 'z') {
|
|
56
|
+
poly.push(p)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return poly;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
15
64
|
|
|
16
65
|
export function pathDataToPolygon(pathData, {
|
|
17
66
|
angles = [],
|
|
18
67
|
split = 0,
|
|
19
68
|
getPathData = true,
|
|
20
|
-
width=0,
|
|
21
|
-
height=0
|
|
69
|
+
width = 0,
|
|
70
|
+
height = 0
|
|
22
71
|
} = {}) {
|
|
23
72
|
|
|
24
73
|
|
|
@@ -43,9 +92,9 @@ export function pathDataToPolygon(pathData, {
|
|
|
43
92
|
|
|
44
93
|
split = !split ? 1 : split;
|
|
45
94
|
|
|
46
|
-
if(width && height){
|
|
47
|
-
minLength = (width+height) * 0.025 / split
|
|
48
|
-
}else{
|
|
95
|
+
if (width && height) {
|
|
96
|
+
minLength = (width + height) * 0.025 / split
|
|
97
|
+
} else {
|
|
49
98
|
//let areas = pathData.map(com => com.cptArea || 0).filter(Boolean).sort()
|
|
50
99
|
let lengths = pathData.map(com => com.dimA || 0).filter(Boolean).sort()
|
|
51
100
|
minLength = lengths[0]
|
|
@@ -75,8 +124,8 @@ export function pathDataToPolygon(pathData, {
|
|
|
75
124
|
split = Math.ceil(length / minLength)
|
|
76
125
|
|
|
77
126
|
let tArr = []
|
|
78
|
-
for(let i=1; i<split; i++){
|
|
79
|
-
tArr.push(1/split*i)
|
|
127
|
+
for (let i = 1; i < split; i++) {
|
|
128
|
+
tArr.push(1 / split * i)
|
|
80
129
|
}
|
|
81
130
|
|
|
82
131
|
tArr.forEach(t => {
|
|
@@ -92,10 +141,10 @@ export function pathDataToPolygon(pathData, {
|
|
|
92
141
|
}
|
|
93
142
|
|
|
94
143
|
|
|
95
|
-
p.area = com.cptArea|| 0
|
|
96
|
-
p.isExtreme = com.extreme|| false
|
|
97
|
-
p.isCorner = com.corner|| false
|
|
98
|
-
p.isDirChange = com.directionChange || false
|
|
144
|
+
p.area = com.cptArea || 0
|
|
145
|
+
p.isExtreme = com.extreme || false
|
|
146
|
+
p.isCorner = com.corner || false
|
|
147
|
+
p.isDirChange = com.directionChange || false;
|
|
99
148
|
|
|
100
149
|
// segment end point
|
|
101
150
|
pts.push(p)
|
|
@@ -115,7 +164,7 @@ export function pathDataToPolygon(pathData, {
|
|
|
115
164
|
|
|
116
165
|
// reduce poly vertices
|
|
117
166
|
//pts = simplifyRD(pts, { quality: 0.5, exclude: ptsEnd, width, height })
|
|
118
|
-
pts = simplifyRD(pts, {quality:0.5, width, height})
|
|
167
|
+
pts = simplifyRD(pts, { quality: 0.5, width, height })
|
|
119
168
|
//pts = simplifyRDP(pts, { quality: 0.8, width, height })
|
|
120
169
|
//console.log(ptsEnd);
|
|
121
170
|
|
package/src/svgii/rounding.js
CHANGED
|
@@ -34,6 +34,8 @@ export function detectAccuracy(pathData) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
let dim_min = dims.sort()
|
|
37
|
+
//console.log('dim_min', dim_min);
|
|
38
|
+
|
|
37
39
|
let sliceIdx = Math.ceil(dim_min.length / 8);
|
|
38
40
|
dim_min = dim_min.slice(0, sliceIdx);
|
|
39
41
|
let minVal = dim_min.reduce((a, b) => a + b, 0) / sliceIdx;
|
package/src/svgii/svg_cleanup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parsePathDataString } from "./pathData_parse";
|
|
2
|
+
import { shapeElToPath } from "./pathData_parse_els";
|
|
2
3
|
import { svgStylesToAttributes } from "./svg-styles-to-attributes";
|
|
3
4
|
|
|
4
5
|
|
|
@@ -17,28 +18,31 @@ export function cleanUpSVG(svgMarkup, {
|
|
|
17
18
|
removeUnused = true,
|
|
18
19
|
stylesToAttributes = true,
|
|
19
20
|
removePrologue = true,
|
|
21
|
+
removeIds = false,
|
|
22
|
+
removeClassNames = false,
|
|
23
|
+
removeDimensions = false,
|
|
20
24
|
fixHref = true,
|
|
21
25
|
mergePaths = false,
|
|
22
26
|
cleanupSVGAtts = true,
|
|
23
27
|
removeNameSpaced = true,
|
|
24
28
|
attributesToGroup = true,
|
|
29
|
+
shapesToPaths = false,
|
|
25
30
|
decimals = -1,
|
|
26
31
|
excludedEls = [],
|
|
27
32
|
} = {}) {
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
attributesToGroup = cleanupSVGAtts ? true : false;
|
|
30
35
|
|
|
31
36
|
// replace namespaced refs
|
|
32
37
|
if (fixHref) svgMarkup = svgMarkup.replaceAll("xlink:href=", "href=");
|
|
33
38
|
|
|
34
39
|
let svg = new DOMParser()
|
|
35
|
-
//.parseFromString(svgMarkup, "image/svg+xml")
|
|
36
40
|
.parseFromString(svgMarkup, "text/html")
|
|
37
41
|
.querySelector("svg");
|
|
38
|
-
//console.log(svg);
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
if (cleanupSVGAtts) {
|
|
45
|
+
//console.log('cleanupSVGAtts');
|
|
42
46
|
let allowed = ['viewBox', 'xmlns', 'width', 'height', 'id', 'class', 'fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin'];
|
|
43
47
|
removeExcludedAttribues(svg, allowed)
|
|
44
48
|
|
|
@@ -50,11 +54,23 @@ export function cleanUpSVG(svgMarkup, {
|
|
|
50
54
|
let els = svg.querySelectorAll('*')
|
|
51
55
|
let elProps = []
|
|
52
56
|
|
|
57
|
+
let geometryElements = ['polygon', 'polyline', 'line', 'rect', 'circle', 'ellipse']
|
|
58
|
+
|
|
59
|
+
|
|
53
60
|
for (let i = 0; i < els.length; i++) {
|
|
54
61
|
let el = els[i];
|
|
55
62
|
|
|
56
63
|
let name = el.nodeName.toLowerCase();
|
|
57
64
|
|
|
65
|
+
// convert shapes
|
|
66
|
+
if (shapesToPaths && name !== 'path' && geometryElements.includes(name)) {
|
|
67
|
+
let path = shapeElToPath(el);
|
|
68
|
+
el.replaceWith(path)
|
|
69
|
+
name = 'path'
|
|
70
|
+
el = path;
|
|
71
|
+
//console.log('shapesToPaths', el.outerHTML);
|
|
72
|
+
}
|
|
73
|
+
|
|
58
74
|
// remove hidden elements
|
|
59
75
|
let style = el.getAttribute('style') || ''
|
|
60
76
|
let isHiddenByStyle = style ? style.trim().includes('display:none') : false;
|
|
@@ -73,15 +89,35 @@ export function cleanUpSVG(svgMarkup, {
|
|
|
73
89
|
}
|
|
74
90
|
}
|
|
75
91
|
|
|
92
|
+
|
|
76
93
|
// group styles
|
|
77
|
-
//console.log('elProps', elProps);
|
|
78
94
|
if (attributesToGroup || mergePaths) {
|
|
79
95
|
moveAttributesToGroup(elProps, mergePaths)
|
|
80
96
|
}
|
|
81
97
|
|
|
98
|
+
if (removeDimensions) {
|
|
99
|
+
svg.removeAttribute('width')
|
|
100
|
+
svg.removeAttribute('height')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (removeClassNames || removeIds) {
|
|
104
|
+
let att = removeClassNames ? 'class' : 'id';
|
|
105
|
+
let selector = `[${att}]`
|
|
106
|
+
let els = svg.querySelectorAll(selector)
|
|
107
|
+
svg.removeAttribute(att)
|
|
108
|
+
els.forEach(el => {
|
|
109
|
+
el.removeAttribute(att)
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//console.log('!!!svgMarkup', svgMarkup);
|
|
114
|
+
|
|
115
|
+
|
|
82
116
|
if (returnDom) return svg
|
|
83
117
|
let markup = stringifySVG(svg)
|
|
84
|
-
|
|
118
|
+
|
|
119
|
+
//console.log(svg.outerHTML);
|
|
120
|
+
|
|
85
121
|
|
|
86
122
|
return markup;
|
|
87
123
|
}
|
|
@@ -92,11 +128,41 @@ function moveAttributesToGroup(elProps = [], mergePaths = true) {
|
|
|
92
128
|
let combine = [[elProps[0]]]
|
|
93
129
|
let idx = 0;
|
|
94
130
|
let lastProps = '';
|
|
95
|
-
|
|
131
|
+
let l = elProps.length;
|
|
132
|
+
let itemsWithProps = elProps.filter(item => item.propstr)
|
|
133
|
+
let path0;
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
// merge paths without properties
|
|
137
|
+
if (!itemsWithProps.length && mergePaths) {
|
|
138
|
+
let item0 = elProps[0]
|
|
139
|
+
path0 = item0.el
|
|
140
|
+
let dCombined = item0.propsFiltered.d
|
|
141
|
+
|
|
142
|
+
for (let i = 1; i < l; i++) {
|
|
143
|
+
let item = elProps[i]
|
|
144
|
+
let path = item.el;
|
|
145
|
+
|
|
146
|
+
let d = item.propsFiltered.d
|
|
147
|
+
let isAbs = d.startsWith('M')
|
|
148
|
+
let dAbs = isAbs ? d : parsePathDataString(d).pathData.map(com => `${com.type} ${com.values.join(' ')}`).join(' ')
|
|
149
|
+
|
|
150
|
+
dCombined += dAbs;
|
|
151
|
+
|
|
152
|
+
// delete path el
|
|
153
|
+
path.remove();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
path0.setAttribute('d', dCombined)
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
// add to combine chunks
|
|
162
|
+
for (let i = 0; i < l; i++) {
|
|
96
163
|
let item = elProps[i];
|
|
97
164
|
let props = item.propsFiltered;
|
|
98
165
|
let propstr = [];
|
|
99
|
-
//let atts = []
|
|
100
166
|
for (let prop in props) {
|
|
101
167
|
if (prop !== 'd' && prop !== 'id') {
|
|
102
168
|
propstr.push(`${prop}:${props[prop]}`)
|
|
@@ -105,16 +171,15 @@ function moveAttributesToGroup(elProps = [], mergePaths = true) {
|
|
|
105
171
|
propstr = propstr.join('_')
|
|
106
172
|
item.propstr = propstr;
|
|
107
173
|
|
|
108
|
-
if (propstr === lastProps) {
|
|
174
|
+
if (l > 1 && propstr === lastProps) {
|
|
109
175
|
combine[idx].push(item)
|
|
110
176
|
} else {
|
|
111
|
-
if (combine[idx].length) {
|
|
177
|
+
if (l > 1 && combine[idx].length) {
|
|
112
178
|
combine.push([])
|
|
113
179
|
idx++
|
|
114
180
|
}
|
|
115
181
|
}
|
|
116
182
|
lastProps = propstr;
|
|
117
|
-
|
|
118
183
|
}
|
|
119
184
|
|
|
120
185
|
|
|
@@ -153,13 +218,16 @@ function moveAttributesToGroup(elProps = [], mergePaths = true) {
|
|
|
153
218
|
}
|
|
154
219
|
|
|
155
220
|
|
|
156
|
-
//console.log('mergePaths', mergePaths);
|
|
157
|
-
|
|
158
221
|
if (mergePaths) {
|
|
159
|
-
|
|
222
|
+
group = group.filter(Boolean)
|
|
223
|
+
let l = group.length
|
|
224
|
+
// nothing to merge
|
|
225
|
+
if (l === 1) return group[0].el;
|
|
226
|
+
|
|
227
|
+
path0 = group[0].el;
|
|
160
228
|
let dCombined = group[0].propsFiltered.d;
|
|
161
229
|
|
|
162
|
-
for (let i = 1; i <
|
|
230
|
+
for (let i = 1; i < l; i++) {
|
|
163
231
|
let item = group[i]
|
|
164
232
|
let path = item.el;
|
|
165
233
|
let d = item.propsFiltered.d
|
|
@@ -229,13 +297,22 @@ function removeNameSpaceAtts(el) {
|
|
|
229
297
|
});
|
|
230
298
|
}
|
|
231
299
|
|
|
232
|
-
export function stringifySVG(svg) {
|
|
300
|
+
export function stringifySVG(svg, omitNamespace = false) {
|
|
233
301
|
let markup = new XMLSerializer().serializeToString(svg);
|
|
302
|
+
|
|
303
|
+
if (omitNamespace) {
|
|
304
|
+
markup = markup.replaceAll('xmlns="http://www.w3.org/2000/svg"', '')
|
|
305
|
+
}
|
|
306
|
+
|
|
234
307
|
markup = markup
|
|
235
308
|
.replace(/\t/g, "")
|
|
236
309
|
.replace(/[\n\r|]/g, "\n")
|
|
237
310
|
.replace(/\n\s*\n/g, '\n')
|
|
238
311
|
.replace(/ +/g, ' ')
|
|
312
|
+
//.replace(/ +/g, ' ')
|
|
313
|
+
.replace(/> </g, '><')
|
|
314
|
+
.trim()
|
|
315
|
+
|
|
239
316
|
|
|
240
317
|
return markup
|
|
241
318
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* load node polyfills for DOM parsing
|
|
4
|
+
* loads linkedom npm module for DOM parsing and emulation
|
|
5
|
+
*/
|
|
6
|
+
import 'svg-path-simplify/node';
|
|
7
|
+
import { svgPathSimplify } from 'svg-path-simplify';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
let svgMarkup =`<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 210 210"><g transform="translate(-210)"><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.5252" d="M403.6556 126.8938H226.3444"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.608" d="M218.304 101.7193h193.392"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.5248" d="M403.6556 76.545H226.3444"/><rect width="122.6239" height="115.3804" x="253.688" y="46.3265" fill="#fff" stroke="#000" stroke-linecap="round" stroke-width="6.5252" ry="16.3026"/><path d="M278.0097 57.7418c-7.1917 0-12.9815 5.7892-12.9815 12.981v65.9129c0 7.1917 5.7898 12.9815 12.9815 12.9815h72.7384c7.1917 0 12.9815-5.7898 12.9815-12.9815v-65.913c0-7.1917-5.7898-12.981-12.9815-12.981zm19.3197 17.3554h13.427l19.7544 54.3635h-11.266l-4.8227-13.8896h-20.7194l-4.8233 13.8896h-11.3819zm40.5508 0h11.3824v54.3635h-11.3824zm-33.8373 8.3726-7.7936 23.5355h15.6261z"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.5252" d="M340.1744 17.9869v28.3396"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.608" d="m314.856 9.7382.288 36.5883"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-width="6.5252" d="M289.8257 17.5703v28.7562"/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M226.75 194.8457q1.8299 0 3.5484-.5847 1.7185-.6025 2.6574-1.5239v-3.4553h-5.4739v-3.863h9.7702v9.1789q-1.7822 2.0377-4.6464 3.1895-2.8483 1.1518-5.983 1.1518-5.474 0-8.4177-3.3668-2.9438-3.3844-2.9438-9.5863 0-6.1664 2.9597-9.4445 2.9597-3.2959 8.5131-3.2959 7.8926 0 10.0407 6.5031l-4.3281 1.453q-.7002-1.896-2.196-2.8706-1.4957-.9745-3.5166-.9745-3.3098 0-5.0283 2.2326t-1.7185 6.3968q0 4.235 1.7662 6.5563 1.7822 2.3035 4.9965 2.3035z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M241.453 198.5846v-24.967h17.6309v4.04H246.147v6.2728h11.9661v4.0401h-11.966v6.574h13.5891v4.04z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="m276.8421 198.5846-9.7702-19.2258q.2864 2.7997.2864 4.5008v14.725h-4.169v-24.967h5.3625l9.9134 19.3853q-.2865-2.6757-.2865-4.873v-14.5123h4.169v24.967z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M286.7237 198.5846v-24.967h17.631v4.04h-12.9368v6.2728h11.966v4.0401h-11.966v6.574h13.5891v4.04z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="m323.8632 198.5846-5.2033-9.48h-5.5057v9.48H308.46v-24.967h11.2023q4.01 0 6.19 1.9314 2.18 1.9138 2.18 5.5108 0 2.6226-1.3367 4.5363-1.3366 1.896-3.6121 2.4984l6.0626 10.49zm-.557-17.3121q0-3.597-4.1372-3.597h-6.0148v7.3713h6.1421q1.9732 0 2.9916-.9923t1.0184-2.782z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4644" d="m347.8432 198.5846-1.989-6.379h-8.545l-1.989 6.379h-4.6942l8.179-24.967h5.5374l8.1472 24.967zm-6.2695-21.1218-3.2144 10.809h6.4446z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M363.2304 177.6577v20.9269h-4.6941v-20.927h-7.2402v-4.04h19.1904v4.04z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M373.0165 198.5846v-24.967h17.631v4.04h-12.9368v6.2728h11.9661v4.0401h-11.9661v6.574h13.5892v4.04z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/><path stroke="#000" stroke-linecap="round" stroke-width=".4646" d="M414.7388 185.915q0 3.863-1.3685 6.7512-1.3525 2.8706-3.8507 4.3945-2.4824 1.5239-5.6967 1.5239h-9.07v-24.967h8.1153q5.6648 0 8.7677 3.1895 3.103 3.1719 3.103 9.108zm-4.726 0q0-4.0223-1.8776-6.131-1.8777-2.1263-5.3625-2.1263h-3.3257v16.8868h3.9781q3.0234 0 4.8055-2.3213t1.7822-6.3082z" font-family="Liberation Sans" font-size="21.0811" font-weight="700" style="line-height:1.25;-inkscape-font-specification:"Liberation Sans Bold""/></g></svg>`
|
|
12
|
+
|
|
13
|
+
//document = new DOMParser().parseFromString(svgMarkup, 'image/svg+xml').querySelector('svg')
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
let rect = dom.querySelector('rect')
|
|
17
|
+
let pathdata = getPathDataFromEl(rect)
|
|
18
|
+
let newR = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
19
|
+
newR.setAttribute('d','M414.7388 185.915' )
|
|
20
|
+
console.log(newR);
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// try to simplify
|
|
24
|
+
let options = {
|
|
25
|
+
stylesToAttributes:true,
|
|
26
|
+
mergePaths:true,
|
|
27
|
+
shapesToPaths:true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
let svgOpt = svgPathSimplify(svgMarkup, options);
|
|
32
|
+
|
|
33
|
+
// simplified pathData
|
|
34
|
+
console.log(svgOpt)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
let document = new DOMParser().parseFromString(svgMarkup, 'image/svg+xml');
|
|
40
|
+
let svg = document.querySelector('svg');
|
|
41
|
+
let path = svg.querySelector('path');
|
|
42
|
+
let els = svg.querySelectorAll('path')
|
|
43
|
+
let d = path.getAttribute('d').substring(0, 10)
|
|
44
|
+
//console.log(els);
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
//let markup = document.toString()
|
|
48
|
+
let markup = new XMLSerializer().serializeToString(svg)
|
|
49
|
+
*/
|
|
50
|
+
//console.log(markup);
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
*/
|
|
Binary file
|