1
1
import { parsePath } from './index' ;
2
2
import { maximizeAbsolutePath , pathDataToAbsolute , pathDataToRelative , pathDataToString } from './convert' ;
3
- import { Vector3 , m2RotateAroundPointH , degreesToRadians } from 'mz-math' ;
3
+ import { Vector3 , m2RotateAroundPointH , degreesToRadians , Vector2 , m2ScaleAtPointH } from 'mz-math' ;
4
4
import { EPathDataCommand } from './interfaces' ;
5
5
import { getPathBBox } from './bbox' ;
6
6
7
+ // ---------------------- TRANSLATE ----------------------
8
+
7
9
export const translatePath = ( d : string , x : number , y : number , decimalPlaces = 2 ) => {
8
10
if ( ! d ) return d ;
9
11
@@ -20,17 +22,19 @@ export const translatePath = (d: string, x: number, y: number, decimalPlaces = 2
20
22
return pathDataToString ( relative , true , decimalPlaces ) ;
21
23
} ;
22
24
23
- const rotateDot = ( x : number , y : number , cx : number , cy : number , angleRad : number , decimalPlaces = 2 ) => {
25
+ // ---------------------- ROTATE -------------------------
26
+
27
+ const rotateDot = ( point : Vector2 , transformOrigin : Vector2 , angleRad : number , decimalPlaces = 2 ) => {
24
28
return m2RotateAroundPointH (
25
29
angleRad ,
26
- [ cx , cy , 1 ] ,
27
- [ x , y , 1 ] ,
30
+ [ transformOrigin [ 0 ] , transformOrigin [ 1 ] , 1 ] ,
31
+ [ point [ 0 ] , point [ 1 ] , 1 ] ,
28
32
true ,
29
33
decimalPlaces
30
34
) ;
31
35
} ;
32
36
33
- export const rotatePathAroundDot = ( d : string , cx : number , cy : number , angleDegrees : number , decimalPlaces = 2 ) => {
37
+ export const rotatePathAroundPoint = ( d : string , transformOrigin : Vector2 , angleDegrees : number , decimalPlaces = 2 ) => {
34
38
if ( ! d ) return d ;
35
39
36
40
const parsed = parsePath ( d ) ;
@@ -51,35 +55,35 @@ export const rotatePathAroundDot = (d: string, cx: number, cy: number, angleDegr
51
55
// 2 params (x, y)
52
56
53
57
// get the new position after rotation
54
- const pos : Vector3 = rotateDot ( item . params [ 0 ] , item . params [ 1 ] , cx , cy , angleRad , decimalPlaces ) ;
58
+ const pos : Vector3 = rotateDot ( [ item . params [ 0 ] , item . params [ 1 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
55
59
item . params [ 0 ] = pos [ 0 ] ;
56
60
item . params [ 1 ] = pos [ 1 ] ;
57
61
break ;
58
62
}
59
63
60
64
case EPathDataCommand . CubicCurveToAbs :{
61
65
// 6 parameters
62
- const pos1 : Vector3 = rotateDot ( item . params [ 0 ] , item . params [ 1 ] , cx , cy , angleRad , decimalPlaces ) ;
66
+ const pos1 : Vector3 = rotateDot ( [ item . params [ 0 ] , item . params [ 1 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
63
67
item . params [ 0 ] = pos1 [ 0 ] ;
64
68
item . params [ 1 ] = pos1 [ 1 ] ;
65
69
66
- const pos2 : Vector3 = rotateDot ( item . params [ 2 ] , item . params [ 3 ] , cx , cy , angleRad , decimalPlaces ) ;
70
+ const pos2 : Vector3 = rotateDot ( [ item . params [ 2 ] , item . params [ 3 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
67
71
item . params [ 2 ] = pos2 [ 0 ] ;
68
72
item . params [ 3 ] = pos2 [ 1 ] ;
69
73
70
- const pos3 : Vector3 = rotateDot ( item . params [ 4 ] , item . params [ 5 ] , cx , cy , angleRad , decimalPlaces ) ;
74
+ const pos3 : Vector3 = rotateDot ( [ item . params [ 4 ] , item . params [ 5 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
71
75
item . params [ 4 ] = pos3 [ 0 ] ;
72
76
item . params [ 5 ] = pos3 [ 1 ] ;
73
77
break ;
74
78
}
75
79
76
80
case EPathDataCommand . QuadraticCurveToAbs :{
77
81
// 4 parameters
78
- const pos1 : Vector3 = rotateDot ( item . params [ 0 ] , item . params [ 1 ] , cx , cy , angleRad , decimalPlaces ) ;
82
+ const pos1 : Vector3 = rotateDot ( [ item . params [ 0 ] , item . params [ 1 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
79
83
item . params [ 0 ] = pos1 [ 0 ] ;
80
84
item . params [ 1 ] = pos1 [ 1 ] ;
81
85
82
- const pos2 : Vector3 = rotateDot ( item . params [ 2 ] , item . params [ 3 ] , cx , cy , angleRad , decimalPlaces ) ;
86
+ const pos2 : Vector3 = rotateDot ( [ item . params [ 2 ] , item . params [ 3 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
83
87
item . params [ 2 ] = pos2 [ 0 ] ;
84
88
item . params [ 3 ] = pos2 [ 1 ] ;
85
89
break ;
@@ -91,7 +95,7 @@ export const rotatePathAroundDot = (d: string, cx: number, cy: number, angleDegr
91
95
item.params[0] = pos1[0];
92
96
item.params[1] = pos1[1];*/
93
97
94
- const pos2 : Vector3 = rotateDot ( item . params [ 5 ] , item . params [ 6 ] , cx , cy , angleRad , decimalPlaces ) ;
98
+ const pos2 : Vector3 = rotateDot ( [ item . params [ 5 ] , item . params [ 6 ] ] , transformOrigin , angleRad , decimalPlaces ) ;
95
99
item . params [ 5 ] = pos2 [ 0 ] ;
96
100
item . params [ 6 ] = pos2 [ 1 ] ;
97
101
break ;
@@ -115,5 +119,143 @@ export const rotatePath = (d: string, angleDegrees: number, decimalPlaces = 2) =
115
119
const cx = x + w / 2 ;
116
120
const cy = y + h / 2 ;
117
121
118
- return rotatePathAroundDot ( d , cx , cy , angleDegrees , decimalPlaces ) ;
122
+ return rotatePathAroundPoint ( d , [ cx , cy ] , angleDegrees , decimalPlaces ) ;
123
+ } ;
124
+
125
+ // ---------------------- SCALE --------------------------
126
+
127
+ const scaleDot = ( point : Vector2 , scaleVector : Vector2 , transformOrigin : Vector2 , decimalPlaces = 2 ) => {
128
+ return m2ScaleAtPointH (
129
+ [ scaleVector [ 0 ] , scaleVector [ 1 ] , 1 ] ,
130
+ [ transformOrigin [ 0 ] , transformOrigin [ 1 ] , 1 ] ,
131
+ [ point [ 0 ] , point [ 1 ] , 1 ] ,
132
+ decimalPlaces
133
+ ) ;
119
134
} ;
135
+
136
+ export const scalePathAroundPoint = ( d : string , scaleVector : Vector2 , transformOrigin : Vector2 , decimalPlaces = 2 ) => {
137
+ if ( ! d ) return d ;
138
+
139
+ const parsed = parsePath ( d ) ;
140
+ if ( parsed . errors . length > 0 ) return d ;
141
+
142
+ const abs = pathDataToAbsolute ( parsed ) ;
143
+ if ( ! abs || abs . commands . length <= 0 ) return d ;
144
+
145
+ const max = maximizeAbsolutePath ( abs ) ;
146
+ for ( const item of max . commands ) {
147
+
148
+ switch ( item . command ) {
149
+
150
+ case EPathDataCommand . MoveToAbs :
151
+ case EPathDataCommand . LineToAbs :{
152
+ // 2 params (x, y)
153
+
154
+ const pos : Vector3 = scaleDot (
155
+ [ item . params [ 0 ] , item . params [ 1 ] ] ,
156
+ scaleVector ,
157
+ transformOrigin ,
158
+ decimalPlaces
159
+ ) ;
160
+
161
+ item . params [ 0 ] = pos [ 0 ] ;
162
+ item . params [ 1 ] = pos [ 1 ] ;
163
+ break ;
164
+ }
165
+
166
+ case EPathDataCommand . CubicCurveToAbs :{
167
+ // 6 parameters
168
+ const pos1 : Vector3 = scaleDot (
169
+ [ item . params [ 0 ] , item . params [ 1 ] ] ,
170
+ scaleVector ,
171
+ transformOrigin ,
172
+ decimalPlaces
173
+ ) ;
174
+ item . params [ 0 ] = pos1 [ 0 ] ;
175
+ item . params [ 1 ] = pos1 [ 1 ] ;
176
+
177
+ const pos2 : Vector3 = scaleDot (
178
+ [ item . params [ 2 ] , item . params [ 3 ] ] ,
179
+ scaleVector ,
180
+ transformOrigin ,
181
+ decimalPlaces
182
+ ) ;
183
+ item . params [ 2 ] = pos2 [ 0 ] ;
184
+ item . params [ 3 ] = pos2 [ 1 ] ;
185
+
186
+ const pos3 : Vector3 = scaleDot (
187
+ [ item . params [ 4 ] , item . params [ 5 ] ] ,
188
+ scaleVector ,
189
+ transformOrigin ,
190
+ decimalPlaces
191
+ ) ;
192
+ item . params [ 4 ] = pos3 [ 0 ] ;
193
+ item . params [ 5 ] = pos3 [ 1 ] ;
194
+ break ;
195
+ }
196
+
197
+ case EPathDataCommand . QuadraticCurveToAbs :{
198
+ // 4 parameters
199
+ const pos1 : Vector3 = scaleDot (
200
+ [ item . params [ 0 ] , item . params [ 1 ] ] ,
201
+ scaleVector ,
202
+ transformOrigin ,
203
+ decimalPlaces
204
+ ) ;
205
+ item . params [ 0 ] = pos1 [ 0 ] ;
206
+ item . params [ 1 ] = pos1 [ 1 ] ;
207
+
208
+ const pos2 : Vector3 = scaleDot (
209
+ [ item . params [ 2 ] , item . params [ 3 ] ] ,
210
+ scaleVector ,
211
+ transformOrigin ,
212
+ decimalPlaces
213
+ ) ;
214
+ item . params [ 2 ] = pos2 [ 0 ] ;
215
+ item . params [ 3 ] = pos2 [ 1 ] ;
216
+ break ;
217
+ }
218
+
219
+ case EPathDataCommand . ArcAbs :{
220
+ // rx ry x-axis-rotation large-arc-flag sweep-flag x y
221
+ /*
222
+ const pos1: Vector3 = scaleDot(
223
+ [item.params[0], item.params[1]],
224
+ scaleVector,
225
+ transformOrigin,
226
+ decimalPlaces
227
+ );
228
+ item.params[0] = pos1[0];
229
+ item.params[1] = pos1[1];*/
230
+
231
+ const pos2 : Vector3 = scaleDot (
232
+ [ item . params [ 5 ] , item . params [ 6 ] ] ,
233
+ scaleVector ,
234
+ transformOrigin ,
235
+ decimalPlaces
236
+ ) ;
237
+ item . params [ 5 ] = pos2 [ 0 ] ;
238
+ item . params [ 6 ] = pos2 [ 1 ] ;
239
+ break ;
240
+ }
241
+ }
242
+ }
243
+
244
+ //const rel = pathDataToRelative(abs);
245
+ return pathDataToString ( abs , false , decimalPlaces ) ;
246
+ } ;
247
+
248
+ export const scalePath = ( d : string , scaleVector : Vector2 , decimalPlaces = 2 ) => {
249
+
250
+ const bbox = getPathBBox ( d ) ;
251
+
252
+ const x = bbox ?. x ?? 0 ;
253
+ const y = bbox ?. y ?? 0 ;
254
+ const w = bbox ?. w ?? 0 ;
255
+ const h = bbox ?. h ?? 0 ;
256
+
257
+ const cx = x + w / 2 ;
258
+ const cy = y + h / 2 ;
259
+
260
+ return scalePathAroundPoint ( d , scaleVector , [ cx , cy ] , decimalPlaces ) ;
261
+ } ;
0 commit comments