@leafer/path 1.0.0-alpha.21 → 1.0.0-alpha.30
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/package.json +4 -3
- package/src/BezierHelper.ts +117 -79
- package/src/EllipseHelper.ts +70 -0
- package/src/PathBounds.ts +138 -0
- package/src/PathCommandDataHelper.ts +98 -0
- package/src/PathCommandMap.ts +52 -33
- package/src/PathConvert.ts +104 -29
- package/src/PathCorner.ts +10 -0
- package/src/PathCreator.ts +71 -43
- package/src/PathDrawer.ts +85 -0
- package/src/PathHelper.ts +5 -112
- package/src/RectHelper.ts +22 -0
- package/src/index.ts +18 -2
package/src/PathCommandMap.ts
CHANGED
|
@@ -1,37 +1,51 @@
|
|
|
1
1
|
import { INumberMap, IStringMap } from '@leafer/interface'
|
|
2
2
|
|
|
3
|
+
export const CanvasCommandOnlyMap: INumberMap = {
|
|
4
|
+
|
|
5
|
+
N: 21, // rect
|
|
6
|
+
D: 22, // roundRect
|
|
7
|
+
X: 23, // simple roundRect
|
|
8
|
+
G: 24, // ellipse
|
|
9
|
+
F: 25, // simple ellipse
|
|
10
|
+
O: 26, // arc
|
|
11
|
+
P: 27, // simple arc
|
|
12
|
+
U: 28 // arcTo
|
|
13
|
+
|
|
14
|
+
}
|
|
3
15
|
|
|
4
16
|
export const PathCommandMap: INumberMap = {
|
|
5
|
-
|
|
17
|
+
|
|
18
|
+
// svg and canvas
|
|
19
|
+
|
|
20
|
+
M: 1, // moveto
|
|
6
21
|
m: 10,
|
|
7
|
-
L: 2, //lineto
|
|
22
|
+
L: 2, // lineto
|
|
8
23
|
l: 20,
|
|
9
|
-
H: 3, //horizontal lineto
|
|
24
|
+
H: 3, // horizontal lineto
|
|
10
25
|
h: 30,
|
|
11
|
-
V: 4, //vertical lineto
|
|
26
|
+
V: 4, // vertical lineto
|
|
12
27
|
v: 40,
|
|
13
|
-
C: 5, //curveto
|
|
28
|
+
C: 5, // curveto
|
|
14
29
|
c: 50,
|
|
15
|
-
S: 6, //smooth curveto
|
|
30
|
+
S: 6, // smooth curveto
|
|
16
31
|
s: 60,
|
|
17
|
-
Q: 7, //quadratic Belzier curve
|
|
32
|
+
Q: 7, // quadratic Belzier curve
|
|
18
33
|
q: 70,
|
|
19
|
-
T: 8, //smooth quadratic Belzier curveto
|
|
34
|
+
T: 8, // smooth quadratic Belzier curveto
|
|
20
35
|
t: 80,
|
|
21
|
-
A: 9, //
|
|
36
|
+
A: 9, //e lliptical Arc
|
|
22
37
|
a: 90,
|
|
23
|
-
Z: 11, //closepath
|
|
38
|
+
Z: 11, // closepath
|
|
24
39
|
z: 11,
|
|
25
40
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
arc: 103,
|
|
31
|
-
arcTo: 104
|
|
41
|
+
R: 12, // Catmull Rom
|
|
42
|
+
|
|
43
|
+
// canvas
|
|
44
|
+
...CanvasCommandOnlyMap
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
export const PathCommandLengthMap: INumberMap = {
|
|
48
|
+
|
|
35
49
|
M: 3, //moveto
|
|
36
50
|
m: 3,
|
|
37
51
|
L: 3, //lineto
|
|
@@ -53,15 +67,21 @@ export const PathCommandLengthMap: INumberMap = {
|
|
|
53
67
|
Z: 1, //closepath
|
|
54
68
|
z: 1,
|
|
55
69
|
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
// canvas
|
|
71
|
+
|
|
72
|
+
N: 5, // rect
|
|
73
|
+
D: 9, // roundRect
|
|
74
|
+
X: 6, // simple roundRect
|
|
75
|
+
G: 9, // ellipse
|
|
76
|
+
F: 5, // simple ellipse
|
|
77
|
+
O: 7, // arc
|
|
78
|
+
P: 4, // simple arc
|
|
79
|
+
U: 6 // arcTo
|
|
80
|
+
|
|
62
81
|
}
|
|
63
82
|
|
|
64
|
-
export const
|
|
83
|
+
export const NeedConvertToCanvasCommandMap: INumberMap = { // convert to: M L C Q Z
|
|
84
|
+
|
|
65
85
|
// M: 1, //moveto
|
|
66
86
|
m: 10,
|
|
67
87
|
// L: 2, //lineto
|
|
@@ -83,25 +103,24 @@ export const PathCommandNeedConvertMap: INumberMap = { // convert to: M L C Q Z
|
|
|
83
103
|
// Z: 11, //closepath
|
|
84
104
|
// z: 11
|
|
85
105
|
|
|
86
|
-
// 非svg标准的canvas绘图命令
|
|
87
|
-
rect: 100,
|
|
88
|
-
roundRect: 101,
|
|
89
|
-
ellipse: 102,
|
|
90
|
-
arc: 103,
|
|
91
|
-
arcTo: 104
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
|
|
109
|
+
export const NeedConvertToCurveCommandMap: INumberMap = {
|
|
110
|
+
...NeedConvertToCanvasCommandMap,
|
|
111
|
+
...CanvasCommandOnlyMap
|
|
112
|
+
}
|
|
113
|
+
|
|
95
114
|
const P = PathCommandMap
|
|
96
115
|
|
|
97
|
-
export const
|
|
116
|
+
export const PathNumberCommandMap: IStringMap = {}
|
|
98
117
|
for (let key in P) {
|
|
99
|
-
|
|
118
|
+
PathNumberCommandMap[P[key]] = key
|
|
100
119
|
}
|
|
101
120
|
// {1: 'M'}
|
|
102
121
|
|
|
103
|
-
export const
|
|
122
|
+
export const PathNumberCommandLengthMap: INumberMap = {}
|
|
104
123
|
for (let key in P) {
|
|
105
|
-
|
|
124
|
+
PathNumberCommandLengthMap[P[key]] = PathCommandLengthMap[key]
|
|
106
125
|
}
|
|
107
126
|
// {1: 3}
|
package/src/PathConvert.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { IPathCommandData } from '@leafer/interface'
|
|
1
|
+
import { IPathCommandData, IPointData } from '@leafer/interface'
|
|
2
2
|
import { StringNumberMap } from '@leafer/math'
|
|
3
|
-
import {
|
|
3
|
+
import { Debug } from '@leafer/debug'
|
|
4
4
|
|
|
5
|
+
import { PathCommandMap as Command, NeedConvertToCanvasCommandMap, NeedConvertToCurveCommandMap, PathCommandLengthMap, PathNumberCommandMap, PathNumberCommandLengthMap } from './PathCommandMap'
|
|
5
6
|
import { BezierHelper } from './BezierHelper'
|
|
7
|
+
import { EllipseHelper } from './EllipseHelper'
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
interface ICurrentCommand {
|
|
@@ -12,8 +14,12 @@ interface ICurrentCommand {
|
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
const { M, m, L, l, H, h, V, v, C, c, S, s, Q, q, T, t, A, a, Z, z } = Command
|
|
16
|
-
const {
|
|
17
|
+
const { M, m, L, l, H, h, V, v, C, c, S, s, Q, q, T, t, A, a, Z, z, N, D, X, G, F, O, P, U } = Command
|
|
18
|
+
const { rect, roundRect, arcTo, arc, ellipse, quadraticCurveTo } = BezierHelper
|
|
19
|
+
const { ellipticalArc } = EllipseHelper
|
|
20
|
+
const debug = Debug.get('PathConvert')
|
|
21
|
+
|
|
22
|
+
const setEndPoint = {} as IPointData
|
|
17
23
|
|
|
18
24
|
export const PathConvert = {
|
|
19
25
|
|
|
@@ -23,11 +29,11 @@ export const PathConvert = {
|
|
|
23
29
|
let i = 0, len = data.length, count: number, str: string = '', command: number, lastCommand: number
|
|
24
30
|
while (i < len) {
|
|
25
31
|
command = data[i]
|
|
26
|
-
count =
|
|
32
|
+
count = PathNumberCommandLengthMap[command]
|
|
27
33
|
if (command === lastCommand) {
|
|
28
34
|
str += ' ' // 重复的命令可以省略
|
|
29
35
|
} else {
|
|
30
|
-
str +=
|
|
36
|
+
str += PathNumberCommandMap[command]
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
for (let j = 1; j < count; j++) {
|
|
@@ -41,10 +47,11 @@ export const PathConvert = {
|
|
|
41
47
|
return str
|
|
42
48
|
},
|
|
43
49
|
|
|
44
|
-
parse(pathString: string,
|
|
50
|
+
parse(pathString: string, curveMode?: boolean): IPathCommandData {
|
|
45
51
|
|
|
46
|
-
let needConvert: boolean, char: string, num = ''
|
|
52
|
+
let needConvert: boolean, char: string, lastChar: string, num = ''
|
|
47
53
|
const data: IPathCommandData = []
|
|
54
|
+
const convertCommand = curveMode ? NeedConvertToCurveCommandMap : NeedConvertToCanvasCommandMap
|
|
48
55
|
|
|
49
56
|
for (let i = 0, len = pathString.length; i < len; i++) {
|
|
50
57
|
|
|
@@ -59,32 +66,39 @@ export const PathConvert = {
|
|
|
59
66
|
if (num) { pushData(data, Number(num)); num = '' }
|
|
60
67
|
|
|
61
68
|
current.name = Command[char]
|
|
62
|
-
current.length =
|
|
69
|
+
current.length = PathCommandLengthMap[char]
|
|
63
70
|
current.index = 0
|
|
64
71
|
pushData(data, current.name)
|
|
65
72
|
|
|
66
|
-
if (!needConvert &&
|
|
73
|
+
if (!needConvert && convertCommand[char]) needConvert = true
|
|
67
74
|
|
|
68
75
|
} else {
|
|
69
76
|
|
|
70
|
-
if (char === '-') {
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
if (char === '-' || char === '+') {
|
|
78
|
+
|
|
79
|
+
if (lastChar === 'e' || lastChar === 'E') { // L45e-12 21e+22
|
|
80
|
+
num += char
|
|
81
|
+
} else {
|
|
82
|
+
if (num) pushData(data, Number(num)) // L-34-35 L+12+28
|
|
83
|
+
num = char
|
|
84
|
+
}
|
|
85
|
+
|
|
73
86
|
} else {
|
|
74
87
|
if (num) { pushData(data, Number(num)); num = '' }
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
}
|
|
78
91
|
|
|
92
|
+
lastChar = char
|
|
93
|
+
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
if (num) pushData(data, Number(num))
|
|
82
97
|
|
|
83
|
-
|
|
84
|
-
return (convert && needConvert) ? PathConvert.convertToSimple(data) : data
|
|
98
|
+
return needConvert ? PathConvert.toCanvasData(data, curveMode) : data
|
|
85
99
|
},
|
|
86
100
|
|
|
87
|
-
|
|
101
|
+
toCanvasData(old: IPathCommandData, curveMode?: boolean): IPathCommandData {
|
|
88
102
|
|
|
89
103
|
let x = 0, y = 0, x1 = 0, y1 = 0, i = 0, len = old.length, controlX: number, controlY: number, command: number, lastCommand: number, smooth: boolean
|
|
90
104
|
const data: IPathCommandData = []
|
|
@@ -94,7 +108,7 @@ export const PathConvert = {
|
|
|
94
108
|
command = old[i]
|
|
95
109
|
|
|
96
110
|
switch (command) {
|
|
97
|
-
//moveto
|
|
111
|
+
//moveto(x, y)
|
|
98
112
|
case m:
|
|
99
113
|
old[i + 1] += x
|
|
100
114
|
old[i + 2] += y
|
|
@@ -105,7 +119,7 @@ export const PathConvert = {
|
|
|
105
119
|
i += 3
|
|
106
120
|
break
|
|
107
121
|
|
|
108
|
-
//horizontal lineto
|
|
122
|
+
//horizontal lineto(x)
|
|
109
123
|
case h:
|
|
110
124
|
old[i + 1] += x
|
|
111
125
|
case H:
|
|
@@ -114,7 +128,7 @@ export const PathConvert = {
|
|
|
114
128
|
i += 2
|
|
115
129
|
break
|
|
116
130
|
|
|
117
|
-
//vertical lineto
|
|
131
|
+
//vertical lineto(y)
|
|
118
132
|
case v:
|
|
119
133
|
old[i + 1] += y
|
|
120
134
|
case V:
|
|
@@ -123,7 +137,7 @@ export const PathConvert = {
|
|
|
123
137
|
i += 2
|
|
124
138
|
break
|
|
125
139
|
|
|
126
|
-
//lineto
|
|
140
|
+
//lineto(x,y)
|
|
127
141
|
case l:
|
|
128
142
|
old[i + 1] += x
|
|
129
143
|
old[i + 2] += y
|
|
@@ -134,7 +148,7 @@ export const PathConvert = {
|
|
|
134
148
|
i += 3
|
|
135
149
|
break
|
|
136
150
|
|
|
137
|
-
//smooth bezierCurveTo
|
|
151
|
+
//smooth bezierCurveTo(x2, y2, x, y)
|
|
138
152
|
case s: //smooth
|
|
139
153
|
old[i + 1] += x
|
|
140
154
|
old[i + 2] += y
|
|
@@ -153,7 +167,7 @@ export const PathConvert = {
|
|
|
153
167
|
i += 5
|
|
154
168
|
break
|
|
155
169
|
|
|
156
|
-
//bezierCurveTo
|
|
170
|
+
//bezierCurveTo(x1, y1, x2, y2, x, y)
|
|
157
171
|
case c:
|
|
158
172
|
old[i + 1] += x
|
|
159
173
|
old[i + 2] += y
|
|
@@ -171,7 +185,7 @@ export const PathConvert = {
|
|
|
171
185
|
i += 7
|
|
172
186
|
break
|
|
173
187
|
|
|
174
|
-
//smooth quadraticCurveTo
|
|
188
|
+
//smooth quadraticCurveTo(x, y)
|
|
175
189
|
case t:
|
|
176
190
|
old[i + 1] += x
|
|
177
191
|
old[i + 2] += y
|
|
@@ -180,13 +194,13 @@ export const PathConvert = {
|
|
|
180
194
|
smooth = (lastCommand === Q) || (lastCommand === T)
|
|
181
195
|
controlX = smooth ? (x * 2 - controlX) : old[i + 1]
|
|
182
196
|
controlY = smooth ? (y * 2 - controlY) : old[i + 2]
|
|
197
|
+
curveMode ? quadraticCurveTo(data, x, y, controlX, controlY, old[i + 1], old[i + 2]) : data.push(Q, controlX, controlY, old[i + 1], old[i + 2])
|
|
183
198
|
x = old[i + 1]
|
|
184
199
|
y = old[i + 2]
|
|
185
|
-
data.push(Q, controlX, controlY, x, y)
|
|
186
200
|
i += 3
|
|
187
201
|
break
|
|
188
202
|
|
|
189
|
-
//quadraticCurveTo
|
|
203
|
+
//quadraticCurveTo(x1, y1, x, y)
|
|
190
204
|
case q:
|
|
191
205
|
old[i + 1] += x
|
|
192
206
|
old[i + 2] += y
|
|
@@ -196,18 +210,18 @@ export const PathConvert = {
|
|
|
196
210
|
case Q:
|
|
197
211
|
controlX = old[i + 1]
|
|
198
212
|
controlY = old[i + 2]
|
|
213
|
+
curveMode ? quadraticCurveTo(data, x, y, controlX, controlY, old[i + 3], old[i + 4]) : data.push(Q, controlX, controlY, old[i + 3], old[i + 4])
|
|
199
214
|
x = old[i + 3]
|
|
200
215
|
y = old[i + 4]
|
|
201
|
-
data.push(Q, controlX, controlY, x, y)
|
|
202
216
|
i += 5
|
|
203
217
|
break
|
|
204
218
|
|
|
205
|
-
//ellipticalArc
|
|
219
|
+
//ellipticalArc(rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y)
|
|
206
220
|
case a:
|
|
207
221
|
old[i + 6] += x
|
|
208
222
|
old[i + 7] += y
|
|
209
223
|
case A:
|
|
210
|
-
data
|
|
224
|
+
ellipticalArc(data, x, y, old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6], old[i + 7], curveMode) // convert to canvas ellipse or curve
|
|
211
225
|
x = old[i + 6]
|
|
212
226
|
y = old[i + 7]
|
|
213
227
|
i += 8
|
|
@@ -217,6 +231,61 @@ export const PathConvert = {
|
|
|
217
231
|
data.push(Z)
|
|
218
232
|
i++
|
|
219
233
|
break
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
// canvas command
|
|
237
|
+
|
|
238
|
+
case N: // rect(x, y, width, height)
|
|
239
|
+
x = old[i + 1]
|
|
240
|
+
y = old[i + 2]
|
|
241
|
+
curveMode ? rect(data, x, y, old[i + 3], old[i + 4]) : copyData(data, old, i, 5)
|
|
242
|
+
i += 5
|
|
243
|
+
break
|
|
244
|
+
case D: // roundRect(x, y, width, height, radius1, radius2, radius3, radius4)
|
|
245
|
+
x = old[i + 1]
|
|
246
|
+
y = old[i + 2]
|
|
247
|
+
curveMode ? roundRect(data, x, y, old[i + 3], old[i + 4], [old[i + 5], old[i + 6], old[i + 7], old[i + 8]]) : copyData(data, old, i, 9)
|
|
248
|
+
i += 9
|
|
249
|
+
break
|
|
250
|
+
case X: // simple roundRect(x, y, width, height, radius)
|
|
251
|
+
x = old[i + 1]
|
|
252
|
+
y = old[i + 2]
|
|
253
|
+
curveMode ? roundRect(data, x, y, old[i + 3], old[i + 4], old[i + 5]) : copyData(data, old, i, 6)
|
|
254
|
+
i += 6
|
|
255
|
+
break
|
|
256
|
+
case G: // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
|
|
257
|
+
ellipse(curveMode ? data : copyData(data, old, i, 9), old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6], old[i + 7], old[i + 8] as unknown as boolean, null, setEndPoint)
|
|
258
|
+
x = setEndPoint.x
|
|
259
|
+
y = setEndPoint.y
|
|
260
|
+
i += 9
|
|
261
|
+
break
|
|
262
|
+
case F: // simple ellipse(x, y, radiusX, radiusY)
|
|
263
|
+
curveMode ? ellipse(data, old[i + 1], old[i + 2], old[i + 3], old[i + 4], 0, 0, 360, false) : copyData(data, old, i, 5)
|
|
264
|
+
x = old[i + 1] + old[i + 3]
|
|
265
|
+
y = old[i + 2]
|
|
266
|
+
i += 5
|
|
267
|
+
break
|
|
268
|
+
case O: // arc(x, y, radius, startAngle, endAngle, anticlockwise)
|
|
269
|
+
arc(curveMode ? data : copyData(data, old, i, 7), old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6] as unknown as boolean, null, setEndPoint)
|
|
270
|
+
x = setEndPoint.x
|
|
271
|
+
y = setEndPoint.y
|
|
272
|
+
i += 7
|
|
273
|
+
break
|
|
274
|
+
case P: // simple arc(x, y, radius)
|
|
275
|
+
curveMode ? arc(data, old[i + 1], old[i + 2], old[i + 3], 0, 360, false) : copyData(data, old, i, 4)
|
|
276
|
+
x = old[i + 1] + old[i + 3]
|
|
277
|
+
y = old[i + 2]
|
|
278
|
+
i += 4
|
|
279
|
+
break
|
|
280
|
+
case U: // arcTo(x1, y1, x2, y2, radius)
|
|
281
|
+
arcTo(curveMode ? data : copyData(data, old, i, 6), x, y, old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], null, setEndPoint)
|
|
282
|
+
x = setEndPoint.x
|
|
283
|
+
y = setEndPoint.y
|
|
284
|
+
i += 6
|
|
285
|
+
break
|
|
286
|
+
default:
|
|
287
|
+
debug.error(`command: ${command} [index:${i}]`, old)
|
|
288
|
+
return data
|
|
220
289
|
}
|
|
221
290
|
|
|
222
291
|
lastCommand = command
|
|
@@ -226,6 +295,12 @@ export const PathConvert = {
|
|
|
226
295
|
|
|
227
296
|
},
|
|
228
297
|
|
|
298
|
+
copyData(data: IPathCommandData, old: IPathCommandData, index: number, count: number): void {
|
|
299
|
+
for (let i = index, end = index + count; i < end; i++) {
|
|
300
|
+
data.push(old[i])
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
229
304
|
pushData(data: IPathCommandData, num: number) {
|
|
230
305
|
if (current.index === current.length) { // 单个命令,多个数据的情况
|
|
231
306
|
current.index = 1
|
|
@@ -238,4 +313,4 @@ export const PathConvert = {
|
|
|
238
313
|
|
|
239
314
|
}
|
|
240
315
|
|
|
241
|
-
const { current, pushData } = PathConvert
|
|
316
|
+
const { current, pushData, copyData } = PathConvert
|
package/src/PathCreator.ts
CHANGED
|
@@ -1,64 +1,92 @@
|
|
|
1
|
-
import { IPathCommandData } from '@leafer/interface'
|
|
2
|
-
import {
|
|
1
|
+
import { IPathCommandData, IPathDrawer } from '@leafer/interface'
|
|
2
|
+
import { PathCommandDataHelper } from './PathCommandDataHelper'
|
|
3
|
+
import { IPathString } from '@leafer-ui/interface'
|
|
4
|
+
import { PathHelper } from './PathHelper'
|
|
3
5
|
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
const { M, L, C, Q, Z, rect, roundRect, ellipse, arc, arcTo } = PathCommandMap
|
|
7
|
+
const { moveTo, lineTo, quadraticCurveTo, bezierCurveTo, closePath, beginPath, rect, roundRect, ellipse, arc, arcTo, moveToEllipse, moveToArc } = PathCommandDataHelper
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
+
export class PathCreator implements IPathDrawer {
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
data = commandData
|
|
12
|
-
},
|
|
11
|
+
public path: IPathCommandData
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
constructor(path?: IPathCommandData | IPathString) {
|
|
14
|
+
if (path) {
|
|
15
|
+
this.path = typeof path === 'string' ? PathHelper.parse(path) : path
|
|
16
|
+
} else {
|
|
17
|
+
this.path = []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public beginPath(): PathCreator {
|
|
22
|
+
beginPath(this.path)
|
|
23
|
+
return this
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// svg and canvas
|
|
17
27
|
|
|
18
|
-
|
|
28
|
+
public moveTo(x: number, y: number): PathCreator {
|
|
29
|
+
moveTo(this.path, x, y)
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public lineTo(x: number, y: number): PathCreator {
|
|
34
|
+
lineTo(this.path, x, y)
|
|
35
|
+
return this
|
|
36
|
+
}
|
|
19
37
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
public bezierCurveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): PathCreator {
|
|
39
|
+
bezierCurveTo(this.path, x1, y1, x2, y2, x, y)
|
|
40
|
+
return this
|
|
41
|
+
}
|
|
23
42
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
public quadraticCurveTo(x1: number, y1: number, x: number, y: number): PathCreator {
|
|
44
|
+
quadraticCurveTo(this.path, x1, y1, x, y)
|
|
45
|
+
return this
|
|
46
|
+
}
|
|
27
47
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
48
|
+
public closePath(): PathCreator {
|
|
49
|
+
closePath(this.path)
|
|
50
|
+
return this
|
|
51
|
+
}
|
|
31
52
|
|
|
32
|
-
|
|
33
|
-
data.push(Q, x1, y1, x, y)
|
|
34
|
-
},
|
|
53
|
+
// canvas
|
|
35
54
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
55
|
+
public rect(x: number, y: number, width: number, height: number): PathCreator {
|
|
56
|
+
rect(this.path, x, y, width, height)
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
40
59
|
|
|
60
|
+
public roundRect(x: number, y: number, width: number, height: number, cornerRadius: number | number[]): PathCreator {
|
|
61
|
+
roundRect(this.path, x, y, width, height, cornerRadius)
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
41
64
|
|
|
42
|
-
|
|
65
|
+
public ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation?: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
|
|
66
|
+
ellipse(this.path, x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
70
|
+
public arc(x: number, y: number, radius: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
|
|
71
|
+
arc(this.path, x, y, radius, startAngle, endAngle, anticlockwise)
|
|
72
|
+
return this
|
|
73
|
+
}
|
|
47
74
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
public arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): PathCreator {
|
|
76
|
+
arcTo(this.path, x1, y1, x2, y2, radius)
|
|
77
|
+
return this
|
|
78
|
+
}
|
|
51
79
|
|
|
52
|
-
|
|
53
|
-
data.push(ellipse, x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise as unknown as number)
|
|
54
|
-
},
|
|
80
|
+
// moveTo, then draw
|
|
55
81
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
82
|
+
public moveToEllipse(x: number, y: number, radiusX: number, radiusY: number, rotation?: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
|
|
83
|
+
moveToEllipse(this.path, x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
59
86
|
|
|
60
|
-
|
|
61
|
-
|
|
87
|
+
public moveToArc(x: number, y: number, radius: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
|
|
88
|
+
moveToArc(this.path, x, y, radius, startAngle, endAngle, anticlockwise)
|
|
89
|
+
return this
|
|
62
90
|
}
|
|
63
91
|
|
|
64
92
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { IPathDrawer, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { OneRadian, PI2 } from '@leafer/math'
|
|
3
|
+
import { Debug } from '@leafer/debug'
|
|
4
|
+
|
|
5
|
+
import { PathCommandMap as Command } from './PathCommandMap'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const { M, L, C, Q, Z, N, D, X, G, F, O, P, U } = Command
|
|
9
|
+
const debug = Debug.get('PathDrawer')
|
|
10
|
+
|
|
11
|
+
export const PathDrawer = {
|
|
12
|
+
|
|
13
|
+
drawPathByData(drawer: IPathDrawer, data: IPathCommandData): void {
|
|
14
|
+
if (!data) return
|
|
15
|
+
|
|
16
|
+
let command: number
|
|
17
|
+
let i = 0, len = data.length
|
|
18
|
+
|
|
19
|
+
while (i < len) {
|
|
20
|
+
command = data[i]
|
|
21
|
+
switch (command) {
|
|
22
|
+
case M: //moveto(x, y)
|
|
23
|
+
drawer.moveTo(data[i + 1], data[i + 2])
|
|
24
|
+
i += 3
|
|
25
|
+
break
|
|
26
|
+
case L: //lineto(x, y)
|
|
27
|
+
drawer.lineTo(data[i + 1], data[i + 2])
|
|
28
|
+
i += 3
|
|
29
|
+
break
|
|
30
|
+
case C: //bezierCurveTo(x1, y1, x2, y2, x, y)
|
|
31
|
+
drawer.bezierCurveTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])
|
|
32
|
+
i += 7
|
|
33
|
+
break
|
|
34
|
+
case Q: //quadraticCurveTo(x1, y1, x, y)
|
|
35
|
+
drawer.quadraticCurveTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
|
|
36
|
+
i += 5
|
|
37
|
+
break
|
|
38
|
+
case Z: //closepath()
|
|
39
|
+
drawer.closePath()
|
|
40
|
+
i += 1
|
|
41
|
+
break
|
|
42
|
+
|
|
43
|
+
// canvas command
|
|
44
|
+
|
|
45
|
+
case N: // rect(x, y, width, height)
|
|
46
|
+
drawer.rect(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
|
|
47
|
+
i += 5
|
|
48
|
+
break
|
|
49
|
+
case D: // roundRect(x, y, width, height, radius1, radius2, radius3, radius4)
|
|
50
|
+
drawer.roundRect(data[i + 1], data[i + 2], data[i + 3], data[i + 4], [data[i + 5], data[i + 6], data[i + 7], data[i + 8]])
|
|
51
|
+
i += 9
|
|
52
|
+
break
|
|
53
|
+
case X: // simple roundRect(x, y, width, height, radius)
|
|
54
|
+
drawer.roundRect(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5])
|
|
55
|
+
i += 6
|
|
56
|
+
break
|
|
57
|
+
case G: // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
|
|
58
|
+
drawer.ellipse(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5] * OneRadian, data[i + 6] * OneRadian, data[i + 7] * OneRadian, data[i + 8] as unknown as boolean)
|
|
59
|
+
i += 9
|
|
60
|
+
break
|
|
61
|
+
case F: // simple ellipse(x, y, radiusX, radiusY)
|
|
62
|
+
drawer.ellipse(data[i + 1], data[i + 2], data[i + 3], data[i + 4], 0, 0, PI2, false)
|
|
63
|
+
i += 5
|
|
64
|
+
break
|
|
65
|
+
case O: // arc(x, y, radius, startAngle, endAngle, anticlockwise)
|
|
66
|
+
drawer.arc(data[i + 1], data[i + 2], data[i + 3], data[i + 4] * OneRadian, data[i + 5] * OneRadian, data[i + 6] as unknown as boolean)
|
|
67
|
+
i += 7
|
|
68
|
+
break
|
|
69
|
+
case P: // simple arc(x, y, radius)
|
|
70
|
+
drawer.arc(data[i + 1], data[i + 2], data[i + 3], 0, PI2, false)
|
|
71
|
+
i += 4
|
|
72
|
+
break
|
|
73
|
+
case U: // arcTo(x1, y1, x2, y2, radius)
|
|
74
|
+
drawer.arcTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5])
|
|
75
|
+
i += 6
|
|
76
|
+
break
|
|
77
|
+
default:
|
|
78
|
+
debug.error(`command: ${command} [index:${i}]`, data)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}
|