@leafer-in/motion-path 1.0.10 → 1.1.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/dist/motion-path.cjs +37 -17
- package/dist/motion-path.esm.js +38 -18
- package/dist/motion-path.esm.min.js +1 -1
- package/dist/motion-path.js +37 -17
- package/dist/motion-path.min.cjs +1 -1
- package/dist/motion-path.min.js +1 -1
- package/package.json +4 -4
- package/src/HighBezierHelper.ts +27 -7
- package/src/HighCurveHelper.ts +11 -9
- package/src/index.ts +4 -2
- package/types/index.d.ts +5 -3
package/dist/motion-path.cjs
CHANGED
|
@@ -6,23 +6,40 @@ const gaussNodes = [0.1488743389, 0.4333953941, 0.6794095682, 0.8650633666, 0.97
|
|
|
6
6
|
const gaussWeights = [0.2955242247, 0.2692667193, 0.2190863625, 0.1494513491, 0.0666713443];
|
|
7
7
|
const { sqrt } = Math;
|
|
8
8
|
const HighBezierHelper = {
|
|
9
|
-
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
10
|
-
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y;
|
|
9
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, t = 1) {
|
|
10
|
+
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y, half = t / 2;
|
|
11
11
|
for (let i = 0; i < gaussNodes.length; i++) {
|
|
12
|
-
t1 =
|
|
13
|
-
t2 =
|
|
12
|
+
t1 = half * (1 + gaussNodes[i]);
|
|
13
|
+
t2 = half * (1 - gaussNodes[i]);
|
|
14
14
|
d1X = getDerivative(t1, fromX, x1, x2, toX);
|
|
15
15
|
d1Y = getDerivative(t1, fromY, y1, y2, toY);
|
|
16
16
|
d2X = getDerivative(t2, fromX, x1, x2, toX);
|
|
17
17
|
d2Y = getDerivative(t2, fromY, y1, y2, toY);
|
|
18
18
|
distance += gaussWeights[i] * (sqrt(d1X * d1X + d1Y * d1Y) + sqrt(d2X * d2X + d2Y * d2Y));
|
|
19
19
|
}
|
|
20
|
-
return distance *
|
|
20
|
+
return distance * half;
|
|
21
21
|
},
|
|
22
22
|
getDerivative(t, fromV, v1, v2, toV) {
|
|
23
23
|
const o = 1 - t;
|
|
24
24
|
return 3 * o * o * (v1 - fromV) + 6 * o * t * (v2 - v1) + 3 * t * t * (toV - v2);
|
|
25
25
|
},
|
|
26
|
+
getRotation(t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
27
|
+
const dx = getDerivative(t, fromX, x1, x2, toX);
|
|
28
|
+
const dy = getDerivative(t, fromY, y1, y2, toY);
|
|
29
|
+
return Math.atan2(dy, dx) / draw.OneRadian;
|
|
30
|
+
},
|
|
31
|
+
getT(distance, totalDistance, fromX, fromY, x1, y1, x2, y2, toX, toY, precision = 1) {
|
|
32
|
+
let low = 0, high = 1, middle = distance / totalDistance, realPrecision = precision / totalDistance / 3;
|
|
33
|
+
if (middle >= 1)
|
|
34
|
+
return 1;
|
|
35
|
+
if (middle <= 0)
|
|
36
|
+
return 0;
|
|
37
|
+
while (high - low > realPrecision) {
|
|
38
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, middle) < distance ? low = middle : high = middle;
|
|
39
|
+
middle = (low + high) / 2;
|
|
40
|
+
}
|
|
41
|
+
return middle;
|
|
42
|
+
},
|
|
26
43
|
cut(data, t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
27
44
|
const o = 1 - t;
|
|
28
45
|
const ax = o * fromX + t * x1, ay = o * fromY + t * y1;
|
|
@@ -34,7 +51,7 @@ const HighBezierHelper = {
|
|
|
34
51
|
data.push(draw.PathCommandMap.C, ax, ay, bx, by, cx, cy);
|
|
35
52
|
}
|
|
36
53
|
};
|
|
37
|
-
const { getDerivative } = HighBezierHelper;
|
|
54
|
+
const { getDerivative, getDistance } = HighBezierHelper;
|
|
38
55
|
|
|
39
56
|
const { M, L, C, Z } = draw.PathCommandMap;
|
|
40
57
|
const tempPoint = {}, tempFrom = {};
|
|
@@ -102,11 +119,12 @@ const HighCurveHelper = {
|
|
|
102
119
|
}
|
|
103
120
|
return { total, segments, data };
|
|
104
121
|
},
|
|
105
|
-
getDistancePoint(distanceData, motionDistance) {
|
|
122
|
+
getDistancePoint(distanceData, motionDistance, motionPrecision) {
|
|
106
123
|
const { segments, data } = distanceData;
|
|
107
124
|
motionDistance = draw.UnitConvert.number(motionDistance, distanceData.total);
|
|
108
125
|
let total = 0, distance, to = {};
|
|
109
126
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
127
|
+
let x1, y1, x2, y2, t;
|
|
110
128
|
const len = data.length;
|
|
111
129
|
while (i < len) {
|
|
112
130
|
command = data[i];
|
|
@@ -136,11 +154,10 @@ const HighCurveHelper = {
|
|
|
136
154
|
toY = data[i + 6];
|
|
137
155
|
distance = segments[index];
|
|
138
156
|
if (total + distance > motionDistance) {
|
|
139
|
-
|
|
140
|
-
motionDistance
|
|
141
|
-
draw.BezierHelper.getPointAndSet(
|
|
142
|
-
|
|
143
|
-
to.rotation = draw.PointHelper.getAngle(tempFrom, to);
|
|
157
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
158
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
159
|
+
draw.BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, to);
|
|
160
|
+
to.rotation = HighBezierHelper.getRotation(t, x, y, x1, y1, x2, y2, toX, toY);
|
|
144
161
|
return to;
|
|
145
162
|
}
|
|
146
163
|
x = toX;
|
|
@@ -157,11 +174,12 @@ const HighCurveHelper = {
|
|
|
157
174
|
}
|
|
158
175
|
return to;
|
|
159
176
|
},
|
|
160
|
-
getDistancePath(distanceData, motionDistance) {
|
|
177
|
+
getDistancePath(distanceData, motionDistance, motionPrecision) {
|
|
161
178
|
const { segments, data } = distanceData, path = [];
|
|
162
179
|
motionDistance = draw.UnitConvert.number(motionDistance, distanceData.total);
|
|
163
180
|
let total = 0, distance, to = {};
|
|
164
181
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
182
|
+
let x1, y1, x2, y2, t;
|
|
165
183
|
const len = data.length;
|
|
166
184
|
while (i < len) {
|
|
167
185
|
command = data[i];
|
|
@@ -188,12 +206,13 @@ const HighCurveHelper = {
|
|
|
188
206
|
path.push(command, x, y);
|
|
189
207
|
break;
|
|
190
208
|
case C:
|
|
191
|
-
|
|
209
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
192
210
|
toX = data[i + 5];
|
|
193
211
|
toY = data[i + 6];
|
|
194
212
|
distance = segments[index];
|
|
195
213
|
if (total + distance > motionDistance) {
|
|
196
|
-
HighBezierHelper.
|
|
214
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
215
|
+
HighBezierHelper.cut(path, t, x, y, x1, y1, x2, y2, toX, toY);
|
|
197
216
|
return path;
|
|
198
217
|
}
|
|
199
218
|
x = toX;
|
|
@@ -242,6 +261,7 @@ const ui = draw.UI.prototype;
|
|
|
242
261
|
const { updateMatrix, updateAllMatrix } = draw.LeafHelper;
|
|
243
262
|
const { updateBounds } = draw.BranchHelper;
|
|
244
263
|
motionPathType()(ui, 'motionPath');
|
|
264
|
+
motionPathType(1)(ui, 'motionPrecision');
|
|
245
265
|
motionPathType()(ui, 'motion');
|
|
246
266
|
motionPathType(true)(ui, 'motionRotation');
|
|
247
267
|
ui.getMotionPathData = function () {
|
|
@@ -252,7 +272,7 @@ ui.getMotionPoint = function (motionDistance) {
|
|
|
252
272
|
const data = getMotionPathData(path);
|
|
253
273
|
if (!data.total)
|
|
254
274
|
return {};
|
|
255
|
-
const point = HighCurveHelper.getDistancePoint(data, motionDistance);
|
|
275
|
+
const point = HighCurveHelper.getDistancePoint(data, motionDistance, path.motionPrecision);
|
|
256
276
|
draw.MatrixHelper.toOuterPoint(path.localTransform, point);
|
|
257
277
|
const { motionRotation } = this;
|
|
258
278
|
if (motionRotation === false)
|
|
@@ -292,7 +312,7 @@ function updateMotion(leaf) {
|
|
|
292
312
|
if (leaf.motionPath) {
|
|
293
313
|
const data = getMotionPathData(leaf);
|
|
294
314
|
if (data.total)
|
|
295
|
-
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion);
|
|
315
|
+
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion, leaf.motionPrecision);
|
|
296
316
|
}
|
|
297
317
|
else {
|
|
298
318
|
leaf.set(leaf.getMotionPoint(motion));
|
package/dist/motion-path.esm.js
CHANGED
|
@@ -1,26 +1,43 @@
|
|
|
1
|
-
import { PathCommandMap, MatrixHelper, PointHelper, UnitConvert, BezierHelper, decorateLeafAttr, attr, isNull, Transition, UI, LeafHelper, BranchHelper } from '@leafer-ui/draw';
|
|
1
|
+
import { OneRadian, PathCommandMap, MatrixHelper, PointHelper, UnitConvert, BezierHelper, decorateLeafAttr, attr, isNull, Transition, UI, LeafHelper, BranchHelper } from '@leafer-ui/draw';
|
|
2
2
|
|
|
3
3
|
const gaussNodes = [0.1488743389, 0.4333953941, 0.6794095682, 0.8650633666, 0.9739065285];
|
|
4
4
|
const gaussWeights = [0.2955242247, 0.2692667193, 0.2190863625, 0.1494513491, 0.0666713443];
|
|
5
5
|
const { sqrt } = Math;
|
|
6
6
|
const HighBezierHelper = {
|
|
7
|
-
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
8
|
-
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y;
|
|
7
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, t = 1) {
|
|
8
|
+
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y, half = t / 2;
|
|
9
9
|
for (let i = 0; i < gaussNodes.length; i++) {
|
|
10
|
-
t1 =
|
|
11
|
-
t2 =
|
|
10
|
+
t1 = half * (1 + gaussNodes[i]);
|
|
11
|
+
t2 = half * (1 - gaussNodes[i]);
|
|
12
12
|
d1X = getDerivative(t1, fromX, x1, x2, toX);
|
|
13
13
|
d1Y = getDerivative(t1, fromY, y1, y2, toY);
|
|
14
14
|
d2X = getDerivative(t2, fromX, x1, x2, toX);
|
|
15
15
|
d2Y = getDerivative(t2, fromY, y1, y2, toY);
|
|
16
16
|
distance += gaussWeights[i] * (sqrt(d1X * d1X + d1Y * d1Y) + sqrt(d2X * d2X + d2Y * d2Y));
|
|
17
17
|
}
|
|
18
|
-
return distance *
|
|
18
|
+
return distance * half;
|
|
19
19
|
},
|
|
20
20
|
getDerivative(t, fromV, v1, v2, toV) {
|
|
21
21
|
const o = 1 - t;
|
|
22
22
|
return 3 * o * o * (v1 - fromV) + 6 * o * t * (v2 - v1) + 3 * t * t * (toV - v2);
|
|
23
23
|
},
|
|
24
|
+
getRotation(t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
25
|
+
const dx = getDerivative(t, fromX, x1, x2, toX);
|
|
26
|
+
const dy = getDerivative(t, fromY, y1, y2, toY);
|
|
27
|
+
return Math.atan2(dy, dx) / OneRadian;
|
|
28
|
+
},
|
|
29
|
+
getT(distance, totalDistance, fromX, fromY, x1, y1, x2, y2, toX, toY, precision = 1) {
|
|
30
|
+
let low = 0, high = 1, middle = distance / totalDistance, realPrecision = precision / totalDistance / 3;
|
|
31
|
+
if (middle >= 1)
|
|
32
|
+
return 1;
|
|
33
|
+
if (middle <= 0)
|
|
34
|
+
return 0;
|
|
35
|
+
while (high - low > realPrecision) {
|
|
36
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, middle) < distance ? low = middle : high = middle;
|
|
37
|
+
middle = (low + high) / 2;
|
|
38
|
+
}
|
|
39
|
+
return middle;
|
|
40
|
+
},
|
|
24
41
|
cut(data, t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
25
42
|
const o = 1 - t;
|
|
26
43
|
const ax = o * fromX + t * x1, ay = o * fromY + t * y1;
|
|
@@ -32,7 +49,7 @@ const HighBezierHelper = {
|
|
|
32
49
|
data.push(PathCommandMap.C, ax, ay, bx, by, cx, cy);
|
|
33
50
|
}
|
|
34
51
|
};
|
|
35
|
-
const { getDerivative } = HighBezierHelper;
|
|
52
|
+
const { getDerivative, getDistance } = HighBezierHelper;
|
|
36
53
|
|
|
37
54
|
const { M, L, C, Z } = PathCommandMap;
|
|
38
55
|
const tempPoint = {}, tempFrom = {};
|
|
@@ -100,11 +117,12 @@ const HighCurveHelper = {
|
|
|
100
117
|
}
|
|
101
118
|
return { total, segments, data };
|
|
102
119
|
},
|
|
103
|
-
getDistancePoint(distanceData, motionDistance) {
|
|
120
|
+
getDistancePoint(distanceData, motionDistance, motionPrecision) {
|
|
104
121
|
const { segments, data } = distanceData;
|
|
105
122
|
motionDistance = UnitConvert.number(motionDistance, distanceData.total);
|
|
106
123
|
let total = 0, distance, to = {};
|
|
107
124
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
125
|
+
let x1, y1, x2, y2, t;
|
|
108
126
|
const len = data.length;
|
|
109
127
|
while (i < len) {
|
|
110
128
|
command = data[i];
|
|
@@ -134,11 +152,10 @@ const HighCurveHelper = {
|
|
|
134
152
|
toY = data[i + 6];
|
|
135
153
|
distance = segments[index];
|
|
136
154
|
if (total + distance > motionDistance) {
|
|
137
|
-
|
|
138
|
-
motionDistance
|
|
139
|
-
BezierHelper.getPointAndSet(
|
|
140
|
-
|
|
141
|
-
to.rotation = PointHelper.getAngle(tempFrom, to);
|
|
155
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
156
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
157
|
+
BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, to);
|
|
158
|
+
to.rotation = HighBezierHelper.getRotation(t, x, y, x1, y1, x2, y2, toX, toY);
|
|
142
159
|
return to;
|
|
143
160
|
}
|
|
144
161
|
x = toX;
|
|
@@ -155,11 +172,12 @@ const HighCurveHelper = {
|
|
|
155
172
|
}
|
|
156
173
|
return to;
|
|
157
174
|
},
|
|
158
|
-
getDistancePath(distanceData, motionDistance) {
|
|
175
|
+
getDistancePath(distanceData, motionDistance, motionPrecision) {
|
|
159
176
|
const { segments, data } = distanceData, path = [];
|
|
160
177
|
motionDistance = UnitConvert.number(motionDistance, distanceData.total);
|
|
161
178
|
let total = 0, distance, to = {};
|
|
162
179
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
180
|
+
let x1, y1, x2, y2, t;
|
|
163
181
|
const len = data.length;
|
|
164
182
|
while (i < len) {
|
|
165
183
|
command = data[i];
|
|
@@ -186,12 +204,13 @@ const HighCurveHelper = {
|
|
|
186
204
|
path.push(command, x, y);
|
|
187
205
|
break;
|
|
188
206
|
case C:
|
|
189
|
-
|
|
207
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
190
208
|
toX = data[i + 5];
|
|
191
209
|
toY = data[i + 6];
|
|
192
210
|
distance = segments[index];
|
|
193
211
|
if (total + distance > motionDistance) {
|
|
194
|
-
HighBezierHelper.
|
|
212
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
213
|
+
HighBezierHelper.cut(path, t, x, y, x1, y1, x2, y2, toX, toY);
|
|
195
214
|
return path;
|
|
196
215
|
}
|
|
197
216
|
x = toX;
|
|
@@ -240,6 +259,7 @@ const ui = UI.prototype;
|
|
|
240
259
|
const { updateMatrix, updateAllMatrix } = LeafHelper;
|
|
241
260
|
const { updateBounds } = BranchHelper;
|
|
242
261
|
motionPathType()(ui, 'motionPath');
|
|
262
|
+
motionPathType(1)(ui, 'motionPrecision');
|
|
243
263
|
motionPathType()(ui, 'motion');
|
|
244
264
|
motionPathType(true)(ui, 'motionRotation');
|
|
245
265
|
ui.getMotionPathData = function () {
|
|
@@ -250,7 +270,7 @@ ui.getMotionPoint = function (motionDistance) {
|
|
|
250
270
|
const data = getMotionPathData(path);
|
|
251
271
|
if (!data.total)
|
|
252
272
|
return {};
|
|
253
|
-
const point = HighCurveHelper.getDistancePoint(data, motionDistance);
|
|
273
|
+
const point = HighCurveHelper.getDistancePoint(data, motionDistance, path.motionPrecision);
|
|
254
274
|
MatrixHelper.toOuterPoint(path.localTransform, point);
|
|
255
275
|
const { motionRotation } = this;
|
|
256
276
|
if (motionRotation === false)
|
|
@@ -290,7 +310,7 @@ function updateMotion(leaf) {
|
|
|
290
310
|
if (leaf.motionPath) {
|
|
291
311
|
const data = getMotionPathData(leaf);
|
|
292
312
|
if (data.total)
|
|
293
|
-
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion);
|
|
313
|
+
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion, leaf.motionPrecision);
|
|
294
314
|
}
|
|
295
315
|
else {
|
|
296
316
|
leaf.set(leaf.getMotionPoint(motion));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{OneRadian as t,PathCommandMap as e,MatrixHelper as o,PointHelper as n,UnitConvert as a,BezierHelper as i,decorateLeafAttr as r,attr as s,isNull as c,Transition as h,UI as u,LeafHelper as l,BranchHelper as f}from"@leafer-ui/draw";const g=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],m=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:_}=Math,P={getDistance(t,e,o,n,a,i,r,s,c=1){let h,u,l,f,P,p,M=0,y=c/2;for(let c=0;c<g.length;c++)h=y*(1+g[c]),u=y*(1-g[c]),l=d(h,t,o,a,r),f=d(h,e,n,i,s),P=d(u,t,o,a,r),p=d(u,e,n,i,s),M+=m[c]*(_(l*l+f*f)+_(P*P+p*p));return M*y},getDerivative(t,e,o,n,a){const i=1-t;return 3*i*i*(o-e)+6*i*t*(n-o)+3*t*t*(a-n)},getRotation(e,o,n,a,i,r,s,c,h){const u=d(e,o,a,r,c),l=d(e,n,i,s,h);return Math.atan2(l,u)/t},getT(t,e,o,n,a,i,r,s,c,h,u=1){let l=0,f=1,g=t/e,m=u/e/3;if(g>=1)return 1;if(g<=0)return 0;for(;f-l>m;)p(o,n,a,i,r,s,c,h,g)<t?l=g:f=g,g=(l+f)/2;return g},cut(t,o,n,a,i,r,s,c,h,u){const l=1-o,f=l*n+o*i,g=l*a+o*r,m=l*i+o*s,_=l*r+o*c,P=l*f+o*m,d=l*g+o*_,p=l*P+o*(l*m+o*(l*s+o*h)),M=l*d+o*(l*_+o*(l*c+o*u));t.push(e.C,f,g,P,d,p,M)}},{getDerivative:d,getDistance:p}=P,{M:M,L:y,C:b,Z:D}=e,x={},k={},F={transform(t,e){let o,n=0;const a=t.length;for(;n<a;)switch(o=t[n],o){case M:case y:F.transformPoints(t,e,n,1),n+=3;break;case b:F.transformPoints(t,e,n,3),n+=7;break;case D:n+=1}},transformPoints(t,e,n,a){for(let i=n+1,r=i+2*a;i<r;i+=2)x.x=t[i],x.y=t[i+1],o.toOuterPoint(e,x),t[i]=x.x,t[i+1]=x.y},getMotionPathData(t){let e,o,a,i,r=0,s=[],c=0,h=0,u=0;const l=t.length;for(;c<l;){switch(i=t[c],i){case M:case y:o=t[c+1],a=t[c+2],e=i===y&&c>0?n.getDistanceFrom(h,u,o,a):0,h=o,u=a,c+=3;break;case b:o=t[c+5],a=t[c+6],e=P.getDistance(h,u,t[c+1],t[c+2],t[c+3],t[c+4],o,a),h=o,u=a,c+=7;break;case D:c+=1;default:e=0}s.push(e),r+=e}return{total:r,segments:s,data:t}},getDistancePoint(t,e,o){const{segments:r,data:s}=t;e=a.number(e,t.total);let c,h,u,l,f,g,m,_,d,p=0,x={},F=0,R=0,T=0,C=0;const v=s.length;for(;F<v;){switch(l=s[F],l){case M:case y:if(h=s[F+1],u=s[F+2],c=r[R],p+c>e||!t.total)return F||(T=h,C=u),k.x=T,k.y=C,x.x=h,x.y=u,n.getDistancePoint(k,x,e-p,!0),x.rotation=n.getAngle(k,x),x;T=h,C=u,F+=3;break;case b:if(h=s[F+5],u=s[F+6],c=r[R],p+c>e)return f=s[F+1],g=s[F+2],m=s[F+3],_=s[F+4],d=P.getT(e-p,c,T,C,f,g,m,_,h,u,o),i.getPointAndSet(d,T,C,f,g,m,_,h,u,x),x.rotation=P.getRotation(d,T,C,f,g,m,_,h,u),x;T=h,C=u,F+=7;break;case D:F+=1;default:c=0}R++,p+=c}return x},getDistancePath(t,e,o){const{segments:i,data:r}=t,s=[];e=a.number(e,t.total);let c,h,u,l,f,g,m,_,d,p=0,x={},F=0,R=0,T=0,C=0;const v=r.length;for(;F<v;){switch(l=r[F],l){case M:case y:if(h=r[F+1],u=r[F+2],c=i[R],p+c>e||!t.total)return F||(T=h,C=u),k.x=T,k.y=C,x.x=h,x.y=u,n.getDistancePoint(k,x,e-p,!0),s.push(l,x.x,x.y),s;T=h,C=u,F+=3,s.push(l,T,C);break;case b:if(f=r[F+1],g=r[F+2],m=r[F+3],_=r[F+4],h=r[F+5],u=r[F+6],c=i[R],p+c>e)return d=P.getT(e-p,c,T,C,f,g,m,_,h,u,o),P.cut(s,d,T,C,f,g,m,_,h,u),s;T=h,C=u,F+=7,s.push(l,f,g,m,_,h,u);break;case D:F+=1,s.push(l);default:c=0}R++,p+=c}return s}};function R(t){return r(t,(t=>s({set(e){this.__setAttr(t,e),this.__hasMotionPath=this.motionPath||!c(this.motion),this.__layout.matrixChanged||this.__layout.matrixChange()}})))}h.register("motion",(function(t,e,o,n){return t?"object"==typeof t&&(t=a.number(t,n.getMotionTotal())):t=0,e?"object"==typeof e&&(e=a.number(e,n.getMotionTotal())):e=0,h.number(t,e,o)})),h.register("motionRotation",(function(t,e,o){return h.number(t,e,o)}));const T=u.prototype,{updateMatrix:C,updateAllMatrix:v}=l,{updateBounds:w}=f;function A(t){const{motion:e,leaferIsCreated:o}=t;if(!c(e)){if(o&&(t.leafer.created=!1),t.motionPath){const o=B(t);o.total&&(t.__.__pathForRender=F.getDistancePath(o,e,t.motionPrecision))}else t.set(t.getMotionPoint(e)),t.__hasAutoLayout||(t.isBranch?(v(t),w(t,t)):C(t));o&&(t.leafer.created=!0)}}function j(t){const{parent:e}=t;if(!t.motionPath&&e){const{children:t}=e;for(let e=0;e<t.length;e++)if(t[e].motionPath)return t[e]}return t}function B(t){const e=t.__;return e.__pathForMotion?e.__pathForMotion:e.__pathForMotion=F.getMotionPathData(t.getPath(!0,!0))}R()(T,"motionPath"),R(1)(T,"motionPrecision"),R()(T,"motion"),R(!0)(T,"motionRotation"),T.getMotionPathData=function(){return B(j(this))},T.getMotionPoint=function(t){const e=j(this),n=B(e);if(!n.total)return{};const a=F.getDistancePoint(n,t,e.motionPrecision);o.toOuterPoint(e.localTransform,a);const{motionRotation:i}=this;return!1===i?delete a.rotation:"number"==typeof i&&(a.rotation+=i),a},T.getMotionTotal=function(){return this.getMotionPathData().total},T.__updateMotionPath=function(){const t=this.__;if(this.__layout.resized&&t.__pathForMotion&&(t.__pathForMotion=void 0),this.motionPath){let t;const{children:e}=this.parent,{leaferIsReady:o}=this;for(let n=0;n<e.length;n++)t=e[n],c(t.motion)||t.__layout.matrixChanged||(o&&t!==this&&this.leafer.layouter.addExtra(t),A(t))}else A(this)};export{P as HighBezierHelper,F as HighCurveHelper,R as motionPathType};
|
package/dist/motion-path.js
CHANGED
|
@@ -6,23 +6,40 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
6
6
|
const gaussWeights = [0.2955242247, 0.2692667193, 0.2190863625, 0.1494513491, 0.0666713443];
|
|
7
7
|
const { sqrt } = Math;
|
|
8
8
|
const HighBezierHelper = {
|
|
9
|
-
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
10
|
-
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y;
|
|
9
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, t = 1) {
|
|
10
|
+
let distance = 0, t1, t2, d1X, d1Y, d2X, d2Y, half = t / 2;
|
|
11
11
|
for (let i = 0; i < gaussNodes.length; i++) {
|
|
12
|
-
t1 =
|
|
13
|
-
t2 =
|
|
12
|
+
t1 = half * (1 + gaussNodes[i]);
|
|
13
|
+
t2 = half * (1 - gaussNodes[i]);
|
|
14
14
|
d1X = getDerivative(t1, fromX, x1, x2, toX);
|
|
15
15
|
d1Y = getDerivative(t1, fromY, y1, y2, toY);
|
|
16
16
|
d2X = getDerivative(t2, fromX, x1, x2, toX);
|
|
17
17
|
d2Y = getDerivative(t2, fromY, y1, y2, toY);
|
|
18
18
|
distance += gaussWeights[i] * (sqrt(d1X * d1X + d1Y * d1Y) + sqrt(d2X * d2X + d2Y * d2Y));
|
|
19
19
|
}
|
|
20
|
-
return distance *
|
|
20
|
+
return distance * half;
|
|
21
21
|
},
|
|
22
22
|
getDerivative(t, fromV, v1, v2, toV) {
|
|
23
23
|
const o = 1 - t;
|
|
24
24
|
return 3 * o * o * (v1 - fromV) + 6 * o * t * (v2 - v1) + 3 * t * t * (toV - v2);
|
|
25
25
|
},
|
|
26
|
+
getRotation(t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
27
|
+
const dx = getDerivative(t, fromX, x1, x2, toX);
|
|
28
|
+
const dy = getDerivative(t, fromY, y1, y2, toY);
|
|
29
|
+
return Math.atan2(dy, dx) / draw.OneRadian;
|
|
30
|
+
},
|
|
31
|
+
getT(distance, totalDistance, fromX, fromY, x1, y1, x2, y2, toX, toY, precision = 1) {
|
|
32
|
+
let low = 0, high = 1, middle = distance / totalDistance, realPrecision = precision / totalDistance / 3;
|
|
33
|
+
if (middle >= 1)
|
|
34
|
+
return 1;
|
|
35
|
+
if (middle <= 0)
|
|
36
|
+
return 0;
|
|
37
|
+
while (high - low > realPrecision) {
|
|
38
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, middle) < distance ? low = middle : high = middle;
|
|
39
|
+
middle = (low + high) / 2;
|
|
40
|
+
}
|
|
41
|
+
return middle;
|
|
42
|
+
},
|
|
26
43
|
cut(data, t, fromX, fromY, x1, y1, x2, y2, toX, toY) {
|
|
27
44
|
const o = 1 - t;
|
|
28
45
|
const ax = o * fromX + t * x1, ay = o * fromY + t * y1;
|
|
@@ -34,7 +51,7 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
34
51
|
data.push(draw.PathCommandMap.C, ax, ay, bx, by, cx, cy);
|
|
35
52
|
}
|
|
36
53
|
};
|
|
37
|
-
const { getDerivative } = HighBezierHelper;
|
|
54
|
+
const { getDerivative, getDistance } = HighBezierHelper;
|
|
38
55
|
|
|
39
56
|
const { M, L, C, Z } = draw.PathCommandMap;
|
|
40
57
|
const tempPoint = {}, tempFrom = {};
|
|
@@ -102,11 +119,12 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
102
119
|
}
|
|
103
120
|
return { total, segments, data };
|
|
104
121
|
},
|
|
105
|
-
getDistancePoint(distanceData, motionDistance) {
|
|
122
|
+
getDistancePoint(distanceData, motionDistance, motionPrecision) {
|
|
106
123
|
const { segments, data } = distanceData;
|
|
107
124
|
motionDistance = draw.UnitConvert.number(motionDistance, distanceData.total);
|
|
108
125
|
let total = 0, distance, to = {};
|
|
109
126
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
127
|
+
let x1, y1, x2, y2, t;
|
|
110
128
|
const len = data.length;
|
|
111
129
|
while (i < len) {
|
|
112
130
|
command = data[i];
|
|
@@ -136,11 +154,10 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
136
154
|
toY = data[i + 6];
|
|
137
155
|
distance = segments[index];
|
|
138
156
|
if (total + distance > motionDistance) {
|
|
139
|
-
|
|
140
|
-
motionDistance
|
|
141
|
-
draw.BezierHelper.getPointAndSet(
|
|
142
|
-
|
|
143
|
-
to.rotation = draw.PointHelper.getAngle(tempFrom, to);
|
|
157
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
158
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
159
|
+
draw.BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, to);
|
|
160
|
+
to.rotation = HighBezierHelper.getRotation(t, x, y, x1, y1, x2, y2, toX, toY);
|
|
144
161
|
return to;
|
|
145
162
|
}
|
|
146
163
|
x = toX;
|
|
@@ -157,11 +174,12 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
157
174
|
}
|
|
158
175
|
return to;
|
|
159
176
|
},
|
|
160
|
-
getDistancePath(distanceData, motionDistance) {
|
|
177
|
+
getDistancePath(distanceData, motionDistance, motionPrecision) {
|
|
161
178
|
const { segments, data } = distanceData, path = [];
|
|
162
179
|
motionDistance = draw.UnitConvert.number(motionDistance, distanceData.total);
|
|
163
180
|
let total = 0, distance, to = {};
|
|
164
181
|
let i = 0, index = 0, x = 0, y = 0, toX, toY, command;
|
|
182
|
+
let x1, y1, x2, y2, t;
|
|
165
183
|
const len = data.length;
|
|
166
184
|
while (i < len) {
|
|
167
185
|
command = data[i];
|
|
@@ -188,12 +206,13 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
188
206
|
path.push(command, x, y);
|
|
189
207
|
break;
|
|
190
208
|
case C:
|
|
191
|
-
|
|
209
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
|
|
192
210
|
toX = data[i + 5];
|
|
193
211
|
toY = data[i + 6];
|
|
194
212
|
distance = segments[index];
|
|
195
213
|
if (total + distance > motionDistance) {
|
|
196
|
-
HighBezierHelper.
|
|
214
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision);
|
|
215
|
+
HighBezierHelper.cut(path, t, x, y, x1, y1, x2, y2, toX, toY);
|
|
197
216
|
return path;
|
|
198
217
|
}
|
|
199
218
|
x = toX;
|
|
@@ -242,6 +261,7 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
242
261
|
const { updateMatrix, updateAllMatrix } = draw.LeafHelper;
|
|
243
262
|
const { updateBounds } = draw.BranchHelper;
|
|
244
263
|
motionPathType()(ui, 'motionPath');
|
|
264
|
+
motionPathType(1)(ui, 'motionPrecision');
|
|
245
265
|
motionPathType()(ui, 'motion');
|
|
246
266
|
motionPathType(true)(ui, 'motionRotation');
|
|
247
267
|
ui.getMotionPathData = function () {
|
|
@@ -252,7 +272,7 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
252
272
|
const data = getMotionPathData(path);
|
|
253
273
|
if (!data.total)
|
|
254
274
|
return {};
|
|
255
|
-
const point = HighCurveHelper.getDistancePoint(data, motionDistance);
|
|
275
|
+
const point = HighCurveHelper.getDistancePoint(data, motionDistance, path.motionPrecision);
|
|
256
276
|
draw.MatrixHelper.toOuterPoint(path.localTransform, point);
|
|
257
277
|
const { motionRotation } = this;
|
|
258
278
|
if (motionRotation === false)
|
|
@@ -292,7 +312,7 @@ this.LeaferIN.motionPath = (function (exports, draw) {
|
|
|
292
312
|
if (leaf.motionPath) {
|
|
293
313
|
const data = getMotionPathData(leaf);
|
|
294
314
|
if (data.total)
|
|
295
|
-
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion);
|
|
315
|
+
leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion, leaf.motionPrecision);
|
|
296
316
|
}
|
|
297
317
|
else {
|
|
298
318
|
leaf.set(leaf.getMotionPoint(motion));
|
package/dist/motion-path.min.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("@leafer-ui/draw");const e=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],o=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:n}=Math,
|
|
1
|
+
"use strict";var t=require("@leafer-ui/draw");const e=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],o=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:n}=Math,r={getDistance(t,r,i,s,c,h,u,l,f=1){let g,m,p,P,_,d,M=0,y=f/2;for(let f=0;f<e.length;f++)g=y*(1+e[f]),m=y*(1-e[f]),p=a(g,t,i,c,u),P=a(g,r,s,h,l),_=a(m,t,i,c,u),d=a(m,r,s,h,l),M+=o[f]*(n(p*p+P*P)+n(_*_+d*d));return M*y},getDerivative(t,e,o,n,r){const a=1-t;return 3*a*a*(o-e)+6*a*t*(n-o)+3*t*t*(r-n)},getRotation(e,o,n,r,i,s,c,h,u){const l=a(e,o,r,s,h),f=a(e,n,i,c,u);return Math.atan2(f,l)/t.OneRadian},getT(t,e,o,n,r,a,s,c,h,u,l=1){let f=0,g=1,m=t/e,p=l/e/3;if(m>=1)return 1;if(m<=0)return 0;for(;g-f>p;)i(o,n,r,a,s,c,h,u,m)<t?f=m:g=m,m=(f+g)/2;return m},cut(e,o,n,r,a,i,s,c,h,u){const l=1-o,f=l*n+o*a,g=l*r+o*i,m=l*a+o*s,p=l*i+o*c,P=l*f+o*m,_=l*g+o*p,d=l*P+o*(l*m+o*(l*s+o*h)),M=l*_+o*(l*p+o*(l*c+o*u));e.push(t.PathCommandMap.C,f,g,P,_,d,M)}},{getDerivative:a,getDistance:i}=r,{M:s,L:c,C:h,Z:u}=t.PathCommandMap,l={},f={},g={transform(t,e){let o,n=0;const r=t.length;for(;n<r;)switch(o=t[n],o){case s:case c:g.transformPoints(t,e,n,1),n+=3;break;case h:g.transformPoints(t,e,n,3),n+=7;break;case u:n+=1}},transformPoints(e,o,n,r){for(let a=n+1,i=a+2*r;a<i;a+=2)l.x=e[a],l.y=e[a+1],t.MatrixHelper.toOuterPoint(o,l),e[a]=l.x,e[a+1]=l.y},getMotionPathData(e){let o,n,a,i,l=0,f=[],g=0,m=0,p=0;const P=e.length;for(;g<P;){switch(i=e[g],i){case s:case c:n=e[g+1],a=e[g+2],o=i===c&&g>0?t.PointHelper.getDistanceFrom(m,p,n,a):0,m=n,p=a,g+=3;break;case h:n=e[g+5],a=e[g+6],o=r.getDistance(m,p,e[g+1],e[g+2],e[g+3],e[g+4],n,a),m=n,p=a,g+=7;break;case u:g+=1;default:o=0}f.push(o),l+=o}return{total:l,segments:f,data:e}},getDistancePoint(e,o,n){const{segments:a,data:i}=e;o=t.UnitConvert.number(o,e.total);let l,g,m,p,P,_,d,M,y,x=0,b={},D=0,C=0,H=0,T=0;const v=i.length;for(;D<v;){switch(p=i[D],p){case s:case c:if(g=i[D+1],m=i[D+2],l=a[C],x+l>o||!e.total)return D||(H=g,T=m),f.x=H,f.y=T,b.x=g,b.y=m,t.PointHelper.getDistancePoint(f,b,o-x,!0),b.rotation=t.PointHelper.getAngle(f,b),b;H=g,T=m,D+=3;break;case h:if(g=i[D+5],m=i[D+6],l=a[C],x+l>o)return P=i[D+1],_=i[D+2],d=i[D+3],M=i[D+4],y=r.getT(o-x,l,H,T,P,_,d,M,g,m,n),t.BezierHelper.getPointAndSet(y,H,T,P,_,d,M,g,m,b),b.rotation=r.getRotation(y,H,T,P,_,d,M,g,m),b;H=g,T=m,D+=7;break;case u:D+=1;default:l=0}C++,x+=l}return b},getDistancePath(e,o,n){const{segments:a,data:i}=e,l=[];o=t.UnitConvert.number(o,e.total);let g,m,p,P,_,d,M,y,x,b=0,D={},C=0,H=0,T=0,v=0;const k=i.length;for(;C<k;){switch(P=i[C],P){case s:case c:if(m=i[C+1],p=i[C+2],g=a[H],b+g>o||!e.total)return C||(T=m,v=p),f.x=T,f.y=v,D.x=m,D.y=p,t.PointHelper.getDistancePoint(f,D,o-b,!0),l.push(P,D.x,D.y),l;T=m,v=p,C+=3,l.push(P,T,v);break;case h:if(_=i[C+1],d=i[C+2],M=i[C+3],y=i[C+4],m=i[C+5],p=i[C+6],g=a[H],b+g>o)return x=r.getT(o-b,g,T,v,_,d,M,y,m,p,n),r.cut(l,x,T,v,_,d,M,y,m,p),l;T=m,v=p,C+=7,l.push(P,_,d,M,y,m,p);break;case u:C+=1,l.push(P);default:g=0}H++,b+=g}return l}};function m(e){return t.decorateLeafAttr(e,(e=>t.attr({set(o){this.__setAttr(e,o),this.__hasMotionPath=this.motionPath||!t.isNull(this.motion),this.__layout.matrixChanged||this.__layout.matrixChange()}})))}t.Transition.register("motion",(function(e,o,n,r){return e?"object"==typeof e&&(e=t.UnitConvert.number(e,r.getMotionTotal())):e=0,o?"object"==typeof o&&(o=t.UnitConvert.number(o,r.getMotionTotal())):o=0,t.Transition.number(e,o,n)})),t.Transition.register("motionRotation",(function(e,o,n){return t.Transition.number(e,o,n)}));const p=t.UI.prototype,{updateMatrix:P,updateAllMatrix:_}=t.LeafHelper,{updateBounds:d}=t.BranchHelper;function M(e){const{motion:o,leaferIsCreated:n}=e;if(!t.isNull(o)){if(n&&(e.leafer.created=!1),e.motionPath){const t=x(e);t.total&&(e.__.__pathForRender=g.getDistancePath(t,o,e.motionPrecision))}else e.set(e.getMotionPoint(o)),e.__hasAutoLayout||(e.isBranch?(_(e),d(e,e)):P(e));n&&(e.leafer.created=!0)}}function y(t){const{parent:e}=t;if(!t.motionPath&&e){const{children:t}=e;for(let e=0;e<t.length;e++)if(t[e].motionPath)return t[e]}return t}function x(t){const e=t.__;return e.__pathForMotion?e.__pathForMotion:e.__pathForMotion=g.getMotionPathData(t.getPath(!0,!0))}m()(p,"motionPath"),m(1)(p,"motionPrecision"),m()(p,"motion"),m(!0)(p,"motionRotation"),p.getMotionPathData=function(){return x(y(this))},p.getMotionPoint=function(e){const o=y(this),n=x(o);if(!n.total)return{};const r=g.getDistancePoint(n,e,o.motionPrecision);t.MatrixHelper.toOuterPoint(o.localTransform,r);const{motionRotation:a}=this;return!1===a?delete r.rotation:"number"==typeof a&&(r.rotation+=a),r},p.getMotionTotal=function(){return this.getMotionPathData().total},p.__updateMotionPath=function(){const e=this.__;if(this.__layout.resized&&e.__pathForMotion&&(e.__pathForMotion=void 0),this.motionPath){let e;const{children:o}=this.parent,{leaferIsReady:n}=this;for(let r=0;r<o.length;r++)e=o[r],t.isNull(e.motion)||e.__layout.matrixChanged||(n&&e!==this&&this.leafer.layouter.addExtra(e),M(e))}else M(this)},exports.HighBezierHelper=r,exports.HighCurveHelper=g,exports.motionPathType=m;
|
package/dist/motion-path.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
this.LeaferIN=this.LeaferIN||{},this.LeaferIN.motionPath=function(t,e){"use strict";const o=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],n=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:a}=Math,
|
|
1
|
+
this.LeaferIN=this.LeaferIN||{},this.LeaferIN.motionPath=function(t,e){"use strict";const o=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],n=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:a}=Math,i={getDistance(t,e,i,s,c,h,u,l,f=1){let g,m,P,p,_,d,M=0,y=f/2;for(let f=0;f<o.length;f++)g=y*(1+o[f]),m=y*(1-o[f]),P=r(g,t,i,c,u),p=r(g,e,s,h,l),_=r(m,t,i,c,u),d=r(m,e,s,h,l),M+=n[f]*(a(P*P+p*p)+a(_*_+d*d));return M*y},getDerivative(t,e,o,n,a){const i=1-t;return 3*i*i*(o-e)+6*i*t*(n-o)+3*t*t*(a-n)},getRotation(t,o,n,a,i,s,c,h,u){const l=r(t,o,a,s,h),f=r(t,n,i,c,u);return Math.atan2(f,l)/e.OneRadian},getT(t,e,o,n,a,i,r,c,h,u,l=1){let f=0,g=1,m=t/e,P=l/e/3;if(m>=1)return 1;if(m<=0)return 0;for(;g-f>P;)s(o,n,a,i,r,c,h,u,m)<t?f=m:g=m,m=(f+g)/2;return m},cut(t,o,n,a,i,r,s,c,h,u){const l=1-o,f=l*n+o*i,g=l*a+o*r,m=l*i+o*s,P=l*r+o*c,p=l*f+o*m,_=l*g+o*P,d=l*p+o*(l*m+o*(l*s+o*h)),M=l*_+o*(l*P+o*(l*c+o*u));t.push(e.PathCommandMap.C,f,g,p,_,d,M)}},{getDerivative:r,getDistance:s}=i,{M:c,L:h,C:u,Z:l}=e.PathCommandMap,f={},g={},m={transform(t,e){let o,n=0;const a=t.length;for(;n<a;)switch(o=t[n],o){case c:case h:m.transformPoints(t,e,n,1),n+=3;break;case u:m.transformPoints(t,e,n,3),n+=7;break;case l:n+=1}},transformPoints(t,o,n,a){for(let i=n+1,r=i+2*a;i<r;i+=2)f.x=t[i],f.y=t[i+1],e.MatrixHelper.toOuterPoint(o,f),t[i]=f.x,t[i+1]=f.y},getMotionPathData(t){let o,n,a,r,s=0,f=[],g=0,m=0,P=0;const p=t.length;for(;g<p;){switch(r=t[g],r){case c:case h:n=t[g+1],a=t[g+2],o=r===h&&g>0?e.PointHelper.getDistanceFrom(m,P,n,a):0,m=n,P=a,g+=3;break;case u:n=t[g+5],a=t[g+6],o=i.getDistance(m,P,t[g+1],t[g+2],t[g+3],t[g+4],n,a),m=n,P=a,g+=7;break;case l:g+=1;default:o=0}f.push(o),s+=o}return{total:s,segments:f,data:t}},getDistancePoint(t,o,n){const{segments:a,data:r}=t;o=e.UnitConvert.number(o,t.total);let s,f,m,P,p,_,d,M,y,b=0,D={},x=0,C=0,H=0,T=0;const v=r.length;for(;x<v;){switch(P=r[x],P){case c:case h:if(f=r[x+1],m=r[x+2],s=a[C],b+s>o||!t.total)return x||(H=f,T=m),g.x=H,g.y=T,D.x=f,D.y=m,e.PointHelper.getDistancePoint(g,D,o-b,!0),D.rotation=e.PointHelper.getAngle(g,D),D;H=f,T=m,x+=3;break;case u:if(f=r[x+5],m=r[x+6],s=a[C],b+s>o)return p=r[x+1],_=r[x+2],d=r[x+3],M=r[x+4],y=i.getT(o-b,s,H,T,p,_,d,M,f,m,n),e.BezierHelper.getPointAndSet(y,H,T,p,_,d,M,f,m,D),D.rotation=i.getRotation(y,H,T,p,_,d,M,f,m),D;H=f,T=m,x+=7;break;case l:x+=1;default:s=0}C++,b+=s}return D},getDistancePath(t,o,n){const{segments:a,data:r}=t,s=[];o=e.UnitConvert.number(o,t.total);let f,m,P,p,_,d,M,y,b,D=0,x={},C=0,H=0,T=0,v=0;const k=r.length;for(;C<k;){switch(p=r[C],p){case c:case h:if(m=r[C+1],P=r[C+2],f=a[H],D+f>o||!t.total)return C||(T=m,v=P),g.x=T,g.y=v,x.x=m,x.y=P,e.PointHelper.getDistancePoint(g,x,o-D,!0),s.push(p,x.x,x.y),s;T=m,v=P,C+=3,s.push(p,T,v);break;case u:if(_=r[C+1],d=r[C+2],M=r[C+3],y=r[C+4],m=r[C+5],P=r[C+6],f=a[H],D+f>o)return b=i.getT(o-D,f,T,v,_,d,M,y,m,P,n),i.cut(s,b,T,v,_,d,M,y,m,P),s;T=m,v=P,C+=7,s.push(p,_,d,M,y,m,P);break;case l:C+=1,s.push(p);default:f=0}H++,D+=f}return s}};function P(t){return e.decorateLeafAttr(t,(t=>e.attr({set(o){this.__setAttr(t,o),this.__hasMotionPath=this.motionPath||!e.isNull(this.motion),this.__layout.matrixChanged||this.__layout.matrixChange()}})))}e.Transition.register("motion",(function(t,o,n,a){return t?"object"==typeof t&&(t=e.UnitConvert.number(t,a.getMotionTotal())):t=0,o?"object"==typeof o&&(o=e.UnitConvert.number(o,a.getMotionTotal())):o=0,e.Transition.number(t,o,n)})),e.Transition.register("motionRotation",(function(t,o,n){return e.Transition.number(t,o,n)}));const p=e.UI.prototype,{updateMatrix:_,updateAllMatrix:d}=e.LeafHelper,{updateBounds:M}=e.BranchHelper;function y(t){const{motion:o,leaferIsCreated:n}=t;if(!e.isNull(o)){if(n&&(t.leafer.created=!1),t.motionPath){const e=D(t);e.total&&(t.__.__pathForRender=m.getDistancePath(e,o,t.motionPrecision))}else t.set(t.getMotionPoint(o)),t.__hasAutoLayout||(t.isBranch?(d(t),M(t,t)):_(t));n&&(t.leafer.created=!0)}}function b(t){const{parent:e}=t;if(!t.motionPath&&e){const{children:t}=e;for(let e=0;e<t.length;e++)if(t[e].motionPath)return t[e]}return t}function D(t){const e=t.__;return e.__pathForMotion?e.__pathForMotion:e.__pathForMotion=m.getMotionPathData(t.getPath(!0,!0))}return P()(p,"motionPath"),P(1)(p,"motionPrecision"),P()(p,"motion"),P(!0)(p,"motionRotation"),p.getMotionPathData=function(){return D(b(this))},p.getMotionPoint=function(t){const o=b(this),n=D(o);if(!n.total)return{};const a=m.getDistancePoint(n,t,o.motionPrecision);e.MatrixHelper.toOuterPoint(o.localTransform,a);const{motionRotation:i}=this;return!1===i?delete a.rotation:"number"==typeof i&&(a.rotation+=i),a},p.getMotionTotal=function(){return this.getMotionPathData().total},p.__updateMotionPath=function(){const t=this.__;if(this.__layout.resized&&t.__pathForMotion&&(t.__pathForMotion=void 0),this.motionPath){let t;const{children:o}=this.parent,{leaferIsReady:n}=this;for(let a=0;a<o.length;a++)t=o[a],e.isNull(t.motion)||t.__layout.matrixChanged||(n&&t!==this&&this.leafer.layouter.addExtra(t),y(t))}else y(this)},t.HighBezierHelper=i,t.HighCurveHelper=m,t.motionPathType=P,t}({},LeaferUI);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-in/motion-path",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "@leafer-in/motion-path",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"leaferjs"
|
|
35
35
|
],
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@leafer-ui/draw": "^1.
|
|
38
|
-
"@leafer-ui/interface": "^1.
|
|
39
|
-
"@leafer-in/interface": "^1.
|
|
37
|
+
"@leafer-ui/draw": "^1.1.1",
|
|
38
|
+
"@leafer-ui/interface": "^1.1.1",
|
|
39
|
+
"@leafer-in/interface": "^1.1.1"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/src/HighBezierHelper.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IPathCommandData } from '@leafer-ui/interface'
|
|
2
|
-
import { PathCommandMap } from '@leafer-ui/draw'
|
|
2
|
+
import { OneRadian, PathCommandMap } from '@leafer-ui/draw'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
// 高斯-勒让德积分节点和权重
|
|
@@ -10,11 +10,11 @@ const { sqrt } = Math
|
|
|
10
10
|
|
|
11
11
|
export const HighBezierHelper = {
|
|
12
12
|
|
|
13
|
-
getDistance(fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number {
|
|
14
|
-
let distance = 0, t1: number, t2: number, d1X: number, d1Y: number, d2X: number, d2Y: number
|
|
13
|
+
getDistance(fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, t = 1): number {
|
|
14
|
+
let distance = 0, t1: number, t2: number, d1X: number, d1Y: number, d2X: number, d2Y: number, half = t / 2
|
|
15
15
|
for (let i = 0; i < gaussNodes.length; i++) {
|
|
16
|
-
t1 =
|
|
17
|
-
t2 =
|
|
16
|
+
t1 = half * (1 + gaussNodes[i])
|
|
17
|
+
t2 = half * (1 - gaussNodes[i])
|
|
18
18
|
|
|
19
19
|
d1X = getDerivative(t1, fromX, x1, x2, toX)
|
|
20
20
|
d1Y = getDerivative(t1, fromY, y1, y2, toY)
|
|
@@ -24,7 +24,7 @@ export const HighBezierHelper = {
|
|
|
24
24
|
|
|
25
25
|
distance += gaussWeights[i] * (sqrt(d1X * d1X + d1Y * d1Y) + sqrt(d2X * d2X + d2Y * d2Y))
|
|
26
26
|
}
|
|
27
|
-
return distance *
|
|
27
|
+
return distance * half
|
|
28
28
|
},
|
|
29
29
|
|
|
30
30
|
getDerivative(t: number, fromV: number, v1: number, v2: number, toV: number): number { // 导数
|
|
@@ -32,6 +32,26 @@ export const HighBezierHelper = {
|
|
|
32
32
|
return 3 * o * o * (v1 - fromV) + 6 * o * t * (v2 - v1) + 3 * t * t * (toV - v2)
|
|
33
33
|
},
|
|
34
34
|
|
|
35
|
+
getRotation(t: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number { // 切线角度
|
|
36
|
+
const dx = getDerivative(t, fromX, x1, x2, toX)
|
|
37
|
+
const dy = getDerivative(t, fromY, y1, y2, toY)
|
|
38
|
+
return Math.atan2(dy, dx) / OneRadian
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
getT(distance: number, totalDistance: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, precision = 1): number { // 弧长反解 t
|
|
42
|
+
let low = 0, high = 1, middle = distance / totalDistance, realPrecision = precision / totalDistance / 3
|
|
43
|
+
|
|
44
|
+
if (middle >= 1) return 1
|
|
45
|
+
if (middle <= 0) return 0
|
|
46
|
+
|
|
47
|
+
while (high - low > realPrecision) { // 2分法快速对比
|
|
48
|
+
getDistance(fromX, fromY, x1, y1, x2, y2, toX, toY, middle) < distance ? low = middle : high = middle
|
|
49
|
+
middle = (low + high) / 2
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return middle
|
|
53
|
+
},
|
|
54
|
+
|
|
35
55
|
cut(data: IPathCommandData, t: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number) {
|
|
36
56
|
const o = 1 - t
|
|
37
57
|
const ax = o * fromX + t * x1, ay = o * fromY + t * y1
|
|
@@ -47,4 +67,4 @@ export const HighBezierHelper = {
|
|
|
47
67
|
|
|
48
68
|
}
|
|
49
69
|
|
|
50
|
-
const { getDerivative } = HighBezierHelper
|
|
70
|
+
const { getDerivative, getDistance } = HighBezierHelper
|
package/src/HighCurveHelper.ts
CHANGED
|
@@ -82,12 +82,13 @@ export const HighCurveHelper = {
|
|
|
82
82
|
},
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
getDistancePoint(distanceData: IMotionPathData, motionDistance: number | IUnitData): IRotationPointData {
|
|
85
|
+
getDistancePoint(distanceData: IMotionPathData, motionDistance: number | IUnitData, motionPrecision?: number): IRotationPointData {
|
|
86
86
|
const { segments, data } = distanceData
|
|
87
87
|
motionDistance = UnitConvert.number(motionDistance, distanceData.total)
|
|
88
88
|
|
|
89
89
|
let total = 0, distance: number, to = {} as IRotationPointData
|
|
90
90
|
let i = 0, index = 0, x: number = 0, y: number = 0, toX: number, toY: number, command: number
|
|
91
|
+
let x1: number, y1: number, x2: number, y2: number, t: number
|
|
91
92
|
|
|
92
93
|
const len = data.length
|
|
93
94
|
while (i < len) {
|
|
@@ -120,11 +121,10 @@ export const HighCurveHelper = {
|
|
|
120
121
|
distance = segments[index]
|
|
121
122
|
|
|
122
123
|
if (total + distance > motionDistance) {
|
|
123
|
-
|
|
124
|
-
motionDistance
|
|
125
|
-
BezierHelper.getPointAndSet(
|
|
126
|
-
|
|
127
|
-
to.rotation = PointHelper.getAngle(tempFrom, to)
|
|
124
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4]
|
|
125
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision)
|
|
126
|
+
BezierHelper.getPointAndSet(t, x, y, x1, y1, x2, y2, toX, toY, to)
|
|
127
|
+
to.rotation = HighBezierHelper.getRotation(t, x, y, x1, y1, x2, y2, toX, toY)
|
|
128
128
|
return to
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -145,12 +145,13 @@ export const HighCurveHelper = {
|
|
|
145
145
|
return to
|
|
146
146
|
},
|
|
147
147
|
|
|
148
|
-
getDistancePath(distanceData: IMotionPathData, motionDistance: number | IUnitData): IPathCommandData {
|
|
148
|
+
getDistancePath(distanceData: IMotionPathData, motionDistance: number | IUnitData, motionPrecision?: number): IPathCommandData {
|
|
149
149
|
const { segments, data } = distanceData, path: IPathCommandData = []
|
|
150
150
|
motionDistance = UnitConvert.number(motionDistance, distanceData.total)
|
|
151
151
|
|
|
152
152
|
let total = 0, distance: number, to = {} as IRotationPointData
|
|
153
153
|
let i = 0, index = 0, x: number = 0, y: number = 0, toX: number, toY: number, command: number
|
|
154
|
+
let x1: number, y1: number, x2: number, y2: number, t: number
|
|
154
155
|
|
|
155
156
|
const len = data.length
|
|
156
157
|
while (i < len) {
|
|
@@ -179,13 +180,14 @@ export const HighCurveHelper = {
|
|
|
179
180
|
path.push(command, x, y)
|
|
180
181
|
break
|
|
181
182
|
case C: //bezierCurveTo(x1, y1, x2, y2, x,y)
|
|
182
|
-
|
|
183
|
+
x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4]
|
|
183
184
|
toX = data[i + 5]
|
|
184
185
|
toY = data[i + 6]
|
|
185
186
|
distance = segments[index]
|
|
186
187
|
|
|
187
188
|
if (total + distance > motionDistance) {
|
|
188
|
-
HighBezierHelper.
|
|
189
|
+
t = HighBezierHelper.getT(motionDistance - total, distance, x, y, x1, y1, x2, y2, toX, toY, motionPrecision)
|
|
190
|
+
HighBezierHelper.cut(path, t, x, y, x1, y1, x2, y2, toX, toY)
|
|
189
191
|
return path
|
|
190
192
|
}
|
|
191
193
|
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,8 @@ const { updateBounds } = BranchHelper
|
|
|
29
29
|
|
|
30
30
|
// addAttr
|
|
31
31
|
motionPathType()(ui, 'motionPath')
|
|
32
|
+
motionPathType(1)(ui, 'motionPrecision')
|
|
33
|
+
|
|
32
34
|
motionPathType()(ui, 'motion')
|
|
33
35
|
motionPathType(true)(ui, 'motionRotation')
|
|
34
36
|
|
|
@@ -42,7 +44,7 @@ ui.getMotionPoint = function (motionDistance: number | IUnitData): IRotationPoin
|
|
|
42
44
|
const data = getMotionPathData(path)
|
|
43
45
|
if (!data.total) return {} as IRotationPointData
|
|
44
46
|
|
|
45
|
-
const point = HighCurveHelper.getDistancePoint(data, motionDistance)
|
|
47
|
+
const point = HighCurveHelper.getDistancePoint(data, motionDistance, path.motionPrecision)
|
|
46
48
|
MatrixHelper.toOuterPoint(path.localTransform, point)
|
|
47
49
|
|
|
48
50
|
const { motionRotation } = this
|
|
@@ -82,7 +84,7 @@ function updateMotion(leaf: IUI): void {
|
|
|
82
84
|
if (leaf.motionPath) {
|
|
83
85
|
|
|
84
86
|
const data = getMotionPathData(leaf)
|
|
85
|
-
if (data.total) leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion) // 生长路径
|
|
87
|
+
if (data.total) leaf.__.__pathForRender = HighCurveHelper.getDistancePath(data, motion, leaf.motionPrecision) // 生长路径
|
|
86
88
|
|
|
87
89
|
} else {
|
|
88
90
|
|
package/types/index.d.ts
CHANGED
|
@@ -5,13 +5,15 @@ declare const HighCurveHelper: {
|
|
|
5
5
|
transform(data: IPathCommandData, matrix: IMatrixData): void;
|
|
6
6
|
transformPoints(data: IPathCommandData, matrix: IMatrixData, start: number, pointCount: number): void;
|
|
7
7
|
getMotionPathData(data: IPathCommandData): IMotionPathData;
|
|
8
|
-
getDistancePoint(distanceData: IMotionPathData, motionDistance: number | IUnitData): IRotationPointData;
|
|
9
|
-
getDistancePath(distanceData: IMotionPathData, motionDistance: number | IUnitData): IPathCommandData;
|
|
8
|
+
getDistancePoint(distanceData: IMotionPathData, motionDistance: number | IUnitData, motionPrecision?: number): IRotationPointData;
|
|
9
|
+
getDistancePath(distanceData: IMotionPathData, motionDistance: number | IUnitData, motionPrecision?: number): IPathCommandData;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
declare const HighBezierHelper: {
|
|
13
|
-
getDistance(fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number;
|
|
13
|
+
getDistance(fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, t?: number): number;
|
|
14
14
|
getDerivative(t: number, fromV: number, v1: number, v2: number, toV: number): number;
|
|
15
|
+
getRotation(t: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): number;
|
|
16
|
+
getT(distance: number, totalDistance: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number, precision?: number): number;
|
|
15
17
|
cut(data: IPathCommandData, t: number, fromX: number, fromY: number, x1: number, y1: number, x2: number, y2: number, toX: number, toY: number): void;
|
|
16
18
|
};
|
|
17
19
|
|