svg-path-simplify 0.3.6 → 0.4.1
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/CHANGELOG.md +24 -0
- package/README.md +38 -85
- package/dist/svg-path-simplify.esm.js +1405 -528
- package/dist/svg-path-simplify.esm.min.js +2 -2
- package/dist/svg-path-simplify.js +1405 -528
- package/dist/svg-path-simplify.min.js +2 -2
- package/dist/svg-path-simplify.pathdata.esm.js +76 -15
- package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
- package/docs/api.md +127 -0
- package/index.html +216 -277
- package/package.json +1 -1
- package/src/constants.js +8 -1
- package/src/pathData_simplify_cubic.js +0 -8
- package/src/pathSimplify-main.js +25 -9
- package/src/svg_flatten_transforms.js +1 -1
- package/src/svgii/convert_colors.js +52 -5
- package/src/svgii/convert_units.js +25 -10
- package/src/svgii/pathData_analyze.js +33 -13
- package/src/svgii/pathData_convert.js +62 -6
- package/src/svgii/pathData_parse_els.js +21 -5
- package/src/svgii/pathData_toPolygon.js +3 -1
- package/src/svgii/pathData_transform.js +307 -0
- package/src/svgii/svg-styles-getTransforms.js +119 -8
- package/src/svgii/svg-styles-to-attributes-const.js +19 -4
- package/src/svgii/svg_cleanup.js +319 -97
- package/src/svgii/svg_el_parse_style_props.js +218 -76
- package/src/svgii/transform_qr_decompose.js +74 -0
- package/src/svgii/pathData_scale.js +0 -42
- package/src/svgii/svg-styles-to-attributes.js +0 -236
|
@@ -4,27 +4,35 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { rad2Deg } from "../constants";
|
|
7
|
+
import { parseColor, rgba2Hex } from "./convert_colors";
|
|
7
8
|
import { getUnit, isNumericValue, normalizeUnits } from "./convert_units";
|
|
8
|
-
import { autoRound } from "./rounding";
|
|
9
|
-
import {
|
|
9
|
+
import { autoRound, roundTo } from "./rounding";
|
|
10
|
+
import { getMatrixFromTransform } from "./svg-styles-getTransforms";
|
|
11
|
+
import { attLookup, colorProps, horizontalProps, strokeAtts, transHorizontal, transVertical, verticalProps } from "./svg-styles-to-attributes-const";
|
|
12
|
+
import { qrDecomposeMatrix } from "./transform_qr_decompose";
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
export function parseStylesProperties(el, {
|
|
16
|
+
fontSize = 16,
|
|
12
17
|
removeNameSpaced = true,
|
|
13
|
-
autoRoundValues =
|
|
18
|
+
autoRoundValues = false,
|
|
19
|
+
minifyRgbColors = false,
|
|
14
20
|
removeInvalid = true,
|
|
15
21
|
removeDefaults = true,
|
|
16
22
|
cleanUpStrokes = true,
|
|
23
|
+
normalizeTransforms = true,
|
|
17
24
|
exclude = [],
|
|
18
25
|
width = 0,
|
|
19
26
|
height = 0,
|
|
20
27
|
} = {}) {
|
|
21
28
|
|
|
29
|
+
//autoRoundValues = false;
|
|
30
|
+
|
|
31
|
+
|
|
22
32
|
let nodeName = el.nodeName.toLowerCase();
|
|
23
33
|
let attProps = getSvgPresentationAtts(el)
|
|
24
34
|
let cssProps = getSvgCssProps(el)
|
|
25
35
|
|
|
26
|
-
console.log('cssProps', cssProps);
|
|
27
|
-
|
|
28
36
|
/**
|
|
29
37
|
* merge props
|
|
30
38
|
* CSS has higher specificity
|
|
@@ -34,29 +42,27 @@ export function parseStylesProperties(el, {
|
|
|
34
42
|
...cssProps,
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
//console.log('!props combined', props);
|
|
46
|
+
|
|
47
|
+
|
|
37
48
|
delete props['style'];
|
|
38
49
|
exclude.push('style')
|
|
39
50
|
|
|
40
51
|
let remove = ['style']
|
|
41
|
-
|
|
42
52
|
let transformsStandalone = ['scale', 'translate', 'rotate'];
|
|
43
53
|
|
|
44
|
-
//let testProp = normalizeUnits(0.5, {unit:'turn'})
|
|
45
|
-
//console.log('testProp', testProp);
|
|
46
|
-
|
|
47
|
-
|
|
48
54
|
/**
|
|
49
55
|
* remove invalid properties
|
|
50
56
|
* e.g font-family for <path>
|
|
51
57
|
*/
|
|
52
58
|
|
|
53
59
|
if (removeInvalid || removeDefaults || removeNameSpaced) {
|
|
54
|
-
let propsFilteredObj = filterSvgElProps(nodeName, props, { removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: transformsStandalone })
|
|
60
|
+
let propsFilteredObj = filterSvgElProps(nodeName, props, { removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: transformsStandalone, cleanUpStrokes: false })
|
|
55
61
|
props = propsFilteredObj.propsFiltered
|
|
56
62
|
remove.push(...propsFilteredObj.remove)
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
//console.log('
|
|
65
|
+
//console.log('???props', nodeName, props, remove);
|
|
60
66
|
|
|
61
67
|
// sanitized prop array
|
|
62
68
|
let propArr = []
|
|
@@ -66,31 +72,48 @@ export function parseStylesProperties(el, {
|
|
|
66
72
|
let valueStr = props[prop];
|
|
67
73
|
|
|
68
74
|
// we parse the path data separately
|
|
69
|
-
if (prop === 'd')
|
|
75
|
+
if (prop === 'd' || prop.startsWith('data-')) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
70
78
|
|
|
71
79
|
let item = { prop, values: [] }
|
|
72
80
|
|
|
81
|
+
// minify rgb values
|
|
82
|
+
if (minifyRgbColors && colorProps.includes(prop)) {
|
|
83
|
+
let color = parseColor(valueStr)
|
|
84
|
+
if (color.mode === 'rgba' || color.mode === 'rgb') {
|
|
85
|
+
let hex = rgba2Hex(color)
|
|
86
|
+
valueStr = hex;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
73
91
|
if (prop === 'transform') {
|
|
74
|
-
//let regex = /(\w+)\(([^)]+)\)/g;
|
|
75
|
-
//let match;
|
|
76
92
|
let transArr = []
|
|
77
93
|
|
|
78
94
|
//split transform functions
|
|
79
95
|
let transFormFunctions = valueStr.split(/(\w+)\(([^)]+)\)/).map(val => val.trim()).filter(Boolean)
|
|
80
|
-
//console.log(transFormFunctions);
|
|
81
96
|
|
|
82
97
|
for (let i = 1; i < transFormFunctions.length; i += 2) {
|
|
83
98
|
let fn = transFormFunctions[i - 1];
|
|
99
|
+
let isHorizontal = transHorizontal.includes(fn);
|
|
100
|
+
let isVertical = transVertical.includes(fn);
|
|
101
|
+
if (isHorizontal) fn = fn.replace('X', '')
|
|
102
|
+
if (isVertical) fn = fn.replace('Y', '')
|
|
84
103
|
let values = transFormFunctions[i].split(/,| /).filter(Boolean)
|
|
85
104
|
let transItem = { fn, values: [] }
|
|
86
105
|
|
|
87
106
|
for (let v = 0; v < values.length; v++) {
|
|
88
|
-
//let { value, unit } = parseValue(values[v])
|
|
89
107
|
let transValues = parseValue(values[v])
|
|
90
|
-
//console.log('!!!transValues', transValues);
|
|
91
108
|
transItem.values.push(...transValues)
|
|
92
|
-
//transItem.units.push(unit)
|
|
93
109
|
}
|
|
110
|
+
|
|
111
|
+
let defaultX = fn.startsWith('scale') ? 1 : 0;
|
|
112
|
+
let defaultY = fn.startsWith('scale') ? 1 : 0;
|
|
113
|
+
|
|
114
|
+
if (isHorizontal) transItem.values = [transItem.values[0], { value: defaultX, unit: '', numeric: true }]
|
|
115
|
+
if (isVertical) transItem.values = [{ value: defaultY, unit: '', numeric: true }, transItem.values[0]]
|
|
116
|
+
|
|
94
117
|
transArr.push(transItem)
|
|
95
118
|
}
|
|
96
119
|
|
|
@@ -98,12 +121,13 @@ export function parseStylesProperties(el, {
|
|
|
98
121
|
if (transArr.length) {
|
|
99
122
|
propArr.push({ prop: 'transforms', values: transArr })
|
|
100
123
|
}
|
|
101
|
-
//console.log('transArr', transArr);
|
|
102
124
|
}
|
|
103
|
-
|
|
125
|
+
|
|
126
|
+
// other props
|
|
104
127
|
else {
|
|
128
|
+
//console.log('other', prop);
|
|
105
129
|
item.values = parseValue(valueStr);
|
|
106
|
-
|
|
130
|
+
|
|
107
131
|
}
|
|
108
132
|
|
|
109
133
|
if (item.values.length) {
|
|
@@ -117,21 +141,28 @@ export function parseStylesProperties(el, {
|
|
|
117
141
|
* user units
|
|
118
142
|
*/
|
|
119
143
|
|
|
120
|
-
console.log('!!!propArr', propArr);
|
|
144
|
+
//console.log('!!!propArr', propArr);
|
|
121
145
|
|
|
122
|
-
let propsNorm = {}
|
|
146
|
+
let propsNorm = { transformArr: [], matrix: null, transComponents: null }
|
|
123
147
|
let transFormOrigin = []
|
|
148
|
+
let normalizedDiagonal = false;
|
|
124
149
|
|
|
125
150
|
for (let i = 0; i < propArr.length; i++) {
|
|
126
151
|
let item = propArr[i];
|
|
127
152
|
let { prop, values } = item;
|
|
128
|
-
//let itemN = {prop}
|
|
129
153
|
let valsNew = [], valX = 0, valY = 0, unitX = '', unitY = '';
|
|
130
154
|
|
|
131
155
|
if (prop !== 'transforms') {
|
|
132
|
-
//console.log('---prop', prop, values, width, height);
|
|
133
156
|
|
|
134
|
-
if (prop === '
|
|
157
|
+
if (cleanUpStrokes && (prop === 'stroke-dasharray' || prop === 'stroke-dashoffset')) {
|
|
158
|
+
normalizedDiagonal = true
|
|
159
|
+
for (let i = 0; i < values.length; i++) {
|
|
160
|
+
let val = normalizeUnits(values[i].value, { unit: values[i].unit, width, height, normalizedDiagonal, fontSize })
|
|
161
|
+
valsNew.push(val)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
else if (prop === 'transform-origin') {
|
|
135
166
|
|
|
136
167
|
values.forEach((item, i) => {
|
|
137
168
|
let val = item.value
|
|
@@ -148,9 +179,8 @@ export function parseStylesProperties(el, {
|
|
|
148
179
|
unitY = values[1] ? values[1].unit : unitX;
|
|
149
180
|
|
|
150
181
|
// normalize units for matrix calculation
|
|
151
|
-
valX = normalizeUnits(valX, { unit: unitX, width, height, isHorizontal: true,
|
|
152
|
-
valY = normalizeUnits(valY, { unit: unitY, width, height, isVertical: true,
|
|
153
|
-
|
|
182
|
+
valX = normalizeUnits(valX, { unit: unitX, width, height, isHorizontal: true, fontSize })
|
|
183
|
+
valY = normalizeUnits(valY, { unit: unitY, width, height, isVertical: true, fontSize })
|
|
154
184
|
transFormOrigin.push(valX, valY)
|
|
155
185
|
|
|
156
186
|
|
|
@@ -159,35 +189,53 @@ export function parseStylesProperties(el, {
|
|
|
159
189
|
for (let v = 0; v < values.length; v++) {
|
|
160
190
|
let val = values[v];
|
|
161
191
|
|
|
162
|
-
let unit = val.unit[v];
|
|
192
|
+
//let unit = val.unit[v];
|
|
193
|
+
let unit = val.unit;
|
|
163
194
|
let valAbs = val.value;
|
|
195
|
+
let isNumeric = val.numeric
|
|
164
196
|
|
|
165
197
|
let isHorizontal = horizontalProps.includes(prop)
|
|
166
198
|
let isVertical = verticalProps.includes(prop)
|
|
167
199
|
|
|
200
|
+
|
|
168
201
|
if (unit) {
|
|
169
|
-
|
|
170
|
-
|
|
202
|
+
if (prop === 'scale' && unit === '%') {
|
|
203
|
+
valAbs = valAbs * 0.01;
|
|
204
|
+
} else {
|
|
205
|
+
if (prop === 'r') normalizedDiagonal = true;
|
|
206
|
+
valAbs = normalizeUnits(val.value, { unit, width, height, isHorizontal, isVertical, normalizedDiagonal, fontSize })
|
|
207
|
+
|
|
208
|
+
if (autoRoundValues && isNumeric) {
|
|
209
|
+
valAbs = autoRound(valAbs)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
//console.log('norm', prop, valAbs, 'val', val, unit, isHorizontal, isVertical, width, height, 'isNumeric', isNumeric);
|
|
213
|
+
}
|
|
171
214
|
}
|
|
172
|
-
|
|
173
215
|
valsNew.push(valAbs)
|
|
174
216
|
}
|
|
175
|
-
|
|
176
217
|
}
|
|
177
218
|
|
|
178
|
-
//propsNorm[prop] = valsNew.length === 1 ? valsNew[0] : valsNew;
|
|
179
219
|
if (valsNew.length) propsNorm[prop] = valsNew;
|
|
180
220
|
|
|
181
|
-
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// is transform properties and functions
|
|
224
|
+
else {
|
|
182
225
|
|
|
183
226
|
let transforms = values || []
|
|
184
|
-
//console.log('transforms', transforms, prop, item);
|
|
185
227
|
|
|
186
228
|
let len = transforms.length
|
|
187
|
-
let
|
|
229
|
+
let transFormAllObj = [];
|
|
230
|
+
|
|
188
231
|
for (let t = 0; len && t < len; t++) {
|
|
189
232
|
let { fn, values } = transforms[t];
|
|
190
|
-
let valsN = [],
|
|
233
|
+
let valsN = [], unitX = '', unitY = '', transformFunctionArr = [];
|
|
234
|
+
|
|
235
|
+
// defaults
|
|
236
|
+
let valX = 0;
|
|
237
|
+
let valY = 0;
|
|
238
|
+
let transObj = {}
|
|
191
239
|
|
|
192
240
|
// console.log('!!!values', values);
|
|
193
241
|
if (fn === 'scale' || fn === 'translate') {
|
|
@@ -197,17 +245,46 @@ export function parseStylesProperties(el, {
|
|
|
197
245
|
unitY = values[1] ? values[1].unit : unitX;
|
|
198
246
|
|
|
199
247
|
if (fn === 'scale') {
|
|
200
|
-
valX = unitX
|
|
201
|
-
valY = unitY
|
|
202
|
-
|
|
248
|
+
valX = unitX === '%' ? valX * 0.01 : valX
|
|
249
|
+
valY = unitY === '%' ? valY * 0.01 : valY
|
|
203
250
|
} else {
|
|
204
|
-
valX = normalizeUnits(valX, { unit: unitX, width, height, isHorizontal: true,
|
|
205
|
-
valY = normalizeUnits(valY, { unit: unitY, width, height, isVertical: true,
|
|
251
|
+
valX = normalizeUnits(valX, { unit: unitX, width, height, isHorizontal: true, fontSize })
|
|
252
|
+
valY = normalizeUnits(valY, { unit: unitY, width, height, isVertical: true, fontSize })
|
|
206
253
|
|
|
207
254
|
}
|
|
208
255
|
valsN.push(valX, valY)
|
|
209
256
|
|
|
210
|
-
|
|
257
|
+
transObj[fn] = valsN;
|
|
258
|
+
transformFunctionArr.push(transObj)
|
|
259
|
+
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (fn === 'matrix') {
|
|
263
|
+
valsN = values.map(val => val.value)
|
|
264
|
+
transObj[fn] = valsN;
|
|
265
|
+
transformFunctionArr.push(transObj)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (fn === 'skew') {
|
|
269
|
+
//valsN = values.map(val => val.value)
|
|
270
|
+
valX = values[0].value
|
|
271
|
+
unitX = values[0].unit
|
|
272
|
+
valY = values[1].value
|
|
273
|
+
unitY = values[1].unit
|
|
274
|
+
//console.log(unitX, unitY);
|
|
275
|
+
|
|
276
|
+
valX = normalizeUnits(valX, { unit: unitX, isHorizontal: true, fontSize })
|
|
277
|
+
valY = normalizeUnits(valY, { unit: unitY, isVertical: true, fontSize })
|
|
278
|
+
|
|
279
|
+
// normalize large angles
|
|
280
|
+
valX = valX > 360 ? (valX % 360) : valX
|
|
281
|
+
valY = valY > 360 ? (valY % 360) : valY
|
|
282
|
+
|
|
283
|
+
//console.log('skew', valX);
|
|
284
|
+
|
|
285
|
+
valsN = [valX, valY]
|
|
286
|
+
transObj[fn] = valsN;
|
|
287
|
+
transformFunctionArr.push(transObj)
|
|
211
288
|
|
|
212
289
|
}
|
|
213
290
|
|
|
@@ -216,69 +293,116 @@ export function parseStylesProperties(el, {
|
|
|
216
293
|
|
|
217
294
|
let angle = values[0].value;
|
|
218
295
|
let unit = values[0].unit;
|
|
219
|
-
angle = normalizeUnits(angle, { unit
|
|
220
|
-
//
|
|
221
|
-
let
|
|
296
|
+
angle = normalizeUnits(angle, { unit })
|
|
297
|
+
//let rot = [`${fn}(${angle})`]
|
|
298
|
+
let hasPivot = values.length === 3;
|
|
299
|
+
let transOrigin = [];
|
|
222
300
|
|
|
223
|
-
|
|
301
|
+
//console.log('values', values);
|
|
302
|
+
if (hasPivot) {
|
|
224
303
|
//console.log('has pivot point');
|
|
225
304
|
let cx = values[1].value
|
|
226
305
|
let cy = values[2].value
|
|
227
|
-
|
|
306
|
+
transOrigin.push({ translate: [cx, cy] }, { translate: [-cx, -cy] })
|
|
307
|
+
|
|
228
308
|
}
|
|
229
|
-
//transFormAll.push(...rot)
|
|
230
|
-
transformFunction = rot
|
|
231
309
|
|
|
310
|
+
transObj[fn] = [angle];
|
|
311
|
+
|
|
312
|
+
if (transOrigin.length) {
|
|
313
|
+
transformFunctionArr.push(transOrigin[0], transObj, transOrigin[1])
|
|
314
|
+
} else {
|
|
315
|
+
transformFunctionArr.push(transObj)
|
|
316
|
+
}
|
|
232
317
|
}
|
|
233
318
|
|
|
234
|
-
|
|
235
|
-
transFormAll.push(...transformFunction)
|
|
236
|
-
//console.log('transFormAll', transFormAll);
|
|
319
|
+
transFormAllObj.push(...transformFunctionArr)
|
|
237
320
|
|
|
238
321
|
}
|
|
239
322
|
|
|
240
|
-
propsNorm['transform'] = transFormAll
|
|
323
|
+
//propsNorm['transform'] = transFormAll
|
|
324
|
+
propsNorm['transformArr'] = transFormAllObj
|
|
241
325
|
|
|
242
326
|
}
|
|
243
327
|
|
|
244
|
-
|
|
245
328
|
//console.log('transFormOrigin', transFormOrigin);
|
|
246
329
|
|
|
247
330
|
}
|
|
248
331
|
|
|
249
332
|
|
|
250
|
-
//
|
|
251
|
-
let translate = propsNorm['translate'] !== undefined ?
|
|
252
|
-
let scale = propsNorm['scale'] !== undefined ?
|
|
253
|
-
let rotate = propsNorm['rotate'] !== undefined ?
|
|
254
|
-
|
|
333
|
+
// prepend standalone transforms before standards
|
|
334
|
+
let translate = propsNorm['translate'] !== undefined ? { translate: propsNorm['translate'] } : null;
|
|
335
|
+
let scale = propsNorm['scale'] !== undefined ? { scale: propsNorm['scale'] } : null;
|
|
336
|
+
let rotate = propsNorm['rotate'] !== undefined ? { rotate: propsNorm['rotate'] } : null;
|
|
255
337
|
let standaloneTransforms = [translate, rotate, scale].filter(Boolean)
|
|
338
|
+
|
|
256
339
|
if (standaloneTransforms.length) {
|
|
257
|
-
remove.push('translate', 'scale', 'rotate')
|
|
258
|
-
propsNorm['
|
|
340
|
+
if (normalizeTransforms) remove.push('translate', 'scale', 'rotate')
|
|
341
|
+
propsNorm['transformArr'] = [...standaloneTransforms, ...propsNorm['transformArr']]
|
|
259
342
|
}
|
|
260
343
|
|
|
261
|
-
console.log('standaloneTransforms', standaloneTransforms);
|
|
262
|
-
//if()
|
|
263
|
-
|
|
264
344
|
|
|
265
345
|
// replace transform-origin with translates
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
propsNorm['
|
|
346
|
+
//console.log('transFormOrigin', transFormOrigin);
|
|
347
|
+
if (transFormOrigin.length && propsNorm['transformArr'] !== undefined) {
|
|
348
|
+
propsNorm['transformArr'] = [
|
|
349
|
+
{ translate: [transFormOrigin[0], transFormOrigin[1]] },
|
|
350
|
+
...propsNorm['transformArr'],
|
|
351
|
+
{ translate: [-transFormOrigin[0], -transFormOrigin[1]] },
|
|
352
|
+
]
|
|
353
|
+
if (normalizeTransforms) remove.push('transform-origin')
|
|
269
354
|
}
|
|
270
355
|
|
|
271
356
|
|
|
357
|
+
/**
|
|
358
|
+
* test run
|
|
359
|
+
* apply parsed transforms
|
|
360
|
+
*/
|
|
361
|
+
let { transformArr = [] } = propsNorm
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
let transAtt = []
|
|
365
|
+
let l = transformArr.length
|
|
366
|
+
if (l) {
|
|
367
|
+
for (let i = 0; l && i < l; i++) {
|
|
368
|
+
let prop = transformArr[i]
|
|
369
|
+
let values = Object.values(prop).flat();
|
|
370
|
+
let name = Object.keys(prop)[0]
|
|
371
|
+
if (name === 'skew') {
|
|
372
|
+
if (values[0]) transAtt.push(`skewX(${values[0]})`)
|
|
373
|
+
if (values[1]) transAtt.push(`skewY(${values[1]})`)
|
|
374
|
+
} else {
|
|
375
|
+
transAtt.push(`${name}(${values.join(' ')})`)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
// consolidate transforms to matrix
|
|
379
|
+
//addTransFormProps(propsNorm);
|
|
380
|
+
}
|
|
272
381
|
|
|
382
|
+
//console.log('parseStylesProperties', props);
|
|
383
|
+
propsNorm.remove = remove
|
|
384
|
+
propsNorm.type = nodeName
|
|
273
385
|
|
|
386
|
+
//console.log('!!!propsNorm', nodeName, JSON.parse(JSON.stringify(propsNorm)));
|
|
387
|
+
return propsNorm
|
|
274
388
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
//console.log('parseStylesProperties', props);
|
|
389
|
+
}
|
|
278
390
|
|
|
391
|
+
/**
|
|
392
|
+
* consolidate transforms to matrix
|
|
393
|
+
*/
|
|
394
|
+
export function addTransFormProps(propsObj = {}, transformArr = []) {
|
|
395
|
+
if (propsObj.transformArr === undefined || !transformArr.length) return;
|
|
279
396
|
|
|
397
|
+
// take existing array or custom
|
|
398
|
+
transformArr = transformArr.length ? transformArr : propsObj.transformArr;
|
|
399
|
+
let matrix = getMatrixFromTransform(transformArr);
|
|
400
|
+
propsObj['matrix'] = matrix;
|
|
280
401
|
|
|
402
|
+
let transComponents = qrDecomposeMatrix(matrix, 3)
|
|
403
|
+
propsObj.transComponents = transComponents;
|
|
281
404
|
|
|
405
|
+
return propsObj
|
|
282
406
|
}
|
|
283
407
|
|
|
284
408
|
/**
|
|
@@ -298,18 +422,25 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
298
422
|
let propsFiltered = {}
|
|
299
423
|
let remove = [];
|
|
300
424
|
|
|
425
|
+
// allow defaults for nested
|
|
426
|
+
//removeDefaults = false;
|
|
301
427
|
|
|
302
428
|
let noStrokeColor = cleanUpStrokes ? (props['stroke'] === undefined) : false;
|
|
429
|
+
//console.log('noStrokeColor', elNodename, 'cleanUpStrokes', cleanUpStrokes);
|
|
303
430
|
|
|
304
431
|
for (let prop in props) {
|
|
305
|
-
let
|
|
306
|
-
|
|
432
|
+
let values = props[prop]
|
|
433
|
+
let value = Array.isArray(values) ? values[0] : values;
|
|
434
|
+
//console.log(prop, Array.isArray(values));
|
|
307
435
|
|
|
308
436
|
// filter out useless
|
|
309
437
|
let isValid = removeInvalid ?
|
|
310
438
|
(attLookup.atts[prop] ? attLookup.atts[prop].includes(elNodename) : false) :
|
|
311
439
|
false;
|
|
312
440
|
|
|
441
|
+
// remove null transforms
|
|
442
|
+
if(prop==='transform' && value==='matrix(1 0 0 1 0 0)') isValid = false;
|
|
443
|
+
|
|
313
444
|
// allow data attributes
|
|
314
445
|
let isDataAtt = allowDataAtts ? prop.startsWith('data-') : false;
|
|
315
446
|
|
|
@@ -318,6 +449,7 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
318
449
|
(attLookup.defaults[prop] ? attLookup.defaults[prop] !== undefined && attLookup.defaults[prop].includes(value) : false) :
|
|
319
450
|
false;
|
|
320
451
|
|
|
452
|
+
|
|
321
453
|
if (isDataAtt || include.includes(prop)) isValid = true;
|
|
322
454
|
if (isDefault) isValid = false
|
|
323
455
|
if (exclude.length && exclude.includes(prop)) isValid = false;
|
|
@@ -331,7 +463,17 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
331
463
|
}
|
|
332
464
|
}
|
|
333
465
|
|
|
466
|
+
/*
|
|
467
|
+
// set explicit stroke width when disabled by stroke color
|
|
468
|
+
if (propsFiltered['stroke'] && propsFiltered['stroke'][0] === 'none') {
|
|
469
|
+
propsFiltered['stroke-width'] = [1]
|
|
470
|
+
remove.push('stroke', 'stroke-width')
|
|
471
|
+
console.log('remove', remove);
|
|
472
|
+
}
|
|
473
|
+
*/
|
|
474
|
+
|
|
334
475
|
|
|
476
|
+
//remove=[]
|
|
335
477
|
return { propsFiltered, remove }
|
|
336
478
|
}
|
|
337
479
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { autoRound, roundTo } from "./rounding";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Decompose matrix to readable transform properties
|
|
5
|
+
* translate() rotate() scale() etc.
|
|
6
|
+
* based on @AndreaBogazzi's answer
|
|
7
|
+
* https://stackoverflow.com/questions/5107134/find-the-rotation-and-skew-of-a-matrix-transformation#32125700
|
|
8
|
+
* return object with seperate transform properties
|
|
9
|
+
* and ready to use css or svg attribute strings
|
|
10
|
+
*/
|
|
11
|
+
export function qrDecomposeMatrix(matrix, precision = 4) {
|
|
12
|
+
let { a, b, c, d, e, f } = matrix;
|
|
13
|
+
// matrix is array
|
|
14
|
+
if (Array.isArray(matrix)) {
|
|
15
|
+
[a, b, c, d, e, f] = matrix;
|
|
16
|
+
}
|
|
17
|
+
let angle = Math.atan2(b, a),
|
|
18
|
+
denom = Math.pow(a, 2) + Math.pow(b, 2),
|
|
19
|
+
scaleX = Math.sqrt(denom),
|
|
20
|
+
scaleY = (a * d - c * b) / scaleX,
|
|
21
|
+
skewX = Math.atan2(a * c + b * d, denom) / (Math.PI / 180),
|
|
22
|
+
translateX = e ? e : 0,
|
|
23
|
+
translateY = f ? f : 0,
|
|
24
|
+
rotate = angle ? angle / (Math.PI / 180) : 0;
|
|
25
|
+
let transObj = {
|
|
26
|
+
translateX: translateX,
|
|
27
|
+
translateY: translateY,
|
|
28
|
+
rotate: rotate,
|
|
29
|
+
scaleX: scaleX,
|
|
30
|
+
scaleY: scaleY,
|
|
31
|
+
skewX: skewX,
|
|
32
|
+
skewY: 0
|
|
33
|
+
};
|
|
34
|
+
let cssTransforms = [];
|
|
35
|
+
let svgTransforms = [];
|
|
36
|
+
for (let prop in transObj) {
|
|
37
|
+
transObj[prop] = +parseFloat(transObj[prop]).toFixed(precision);
|
|
38
|
+
let val = transObj[prop];
|
|
39
|
+
let unit = "";
|
|
40
|
+
if (prop == "rotate" || prop == "skewX") {
|
|
41
|
+
unit = "deg";
|
|
42
|
+
}
|
|
43
|
+
if (prop.indexOf("translate") != -1) {
|
|
44
|
+
unit = "px";
|
|
45
|
+
}
|
|
46
|
+
// combine these properties
|
|
47
|
+
let convert = ["scaleX", "scaleY", "translateX", "translateY"];
|
|
48
|
+
if (val !== 0) {
|
|
49
|
+
cssTransforms.push(`${prop}(${val}${unit})`);
|
|
50
|
+
}
|
|
51
|
+
if (convert.indexOf(prop) == -1 && val !== 0) {
|
|
52
|
+
svgTransforms.push(`${prop}(${val})`);
|
|
53
|
+
} else if (prop == "scaleX") {
|
|
54
|
+
svgTransforms.push(
|
|
55
|
+
`scale(${+scaleX.toFixed(precision)} ${+scaleY.toFixed(precision)})`
|
|
56
|
+
);
|
|
57
|
+
} else if (prop == "translateX") {
|
|
58
|
+
svgTransforms.push(
|
|
59
|
+
`translate(${transObj.translateX} ${transObj.translateY})`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
// append css style string to object
|
|
65
|
+
transObj.cssTransform = cssTransforms.join(" ");
|
|
66
|
+
transObj.svgTransform = svgTransforms.join(" ");
|
|
67
|
+
//transObj.matrix = [a, b, c, d, e, f ].map(val=>autoRound(val))
|
|
68
|
+
transObj.matrix = [a, b, c, d, e, f ].map(val=>roundTo(val, precision))
|
|
69
|
+
transObj.matrixAtt = `matrix(${transObj.matrix.join(' ')})`
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
return transObj;
|
|
74
|
+
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scale pathData
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export function scalePathData(pathData, scaleX, scaleY) {
|
|
6
|
-
pathData.forEach((com, i) => {
|
|
7
|
-
let { type, values } = com;
|
|
8
|
-
let typeRel = type.toLowerCase();
|
|
9
|
-
|
|
10
|
-
switch (typeRel) {
|
|
11
|
-
case "a":
|
|
12
|
-
com.values = [
|
|
13
|
-
values[0] * scaleX,
|
|
14
|
-
values[1] * scaleY,
|
|
15
|
-
values[2],
|
|
16
|
-
values[3],
|
|
17
|
-
values[4],
|
|
18
|
-
values[5] * scaleX,
|
|
19
|
-
values[6] * scaleY
|
|
20
|
-
];
|
|
21
|
-
break;
|
|
22
|
-
|
|
23
|
-
case "h":
|
|
24
|
-
com.values = [values[0] * scaleX];
|
|
25
|
-
break;
|
|
26
|
-
|
|
27
|
-
case "v":
|
|
28
|
-
com.values = [values[0] * scaleY];
|
|
29
|
-
break;
|
|
30
|
-
|
|
31
|
-
default:
|
|
32
|
-
if (values.length) {
|
|
33
|
-
for (let i = 0; i < values.length; i += 2) {
|
|
34
|
-
com.values[i] *= scaleX;
|
|
35
|
-
com.values[i + 1] *= scaleY;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
return pathData;
|
|
42
|
-
}
|