@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.
@@ -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 = 0.5 * (1 + gaussNodes[i]);
13
- t2 = 0.5 * (1 - gaussNodes[i]);
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 * 0.5;
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
140
- motionDistance -= total;
141
- draw.BezierHelper.getPointAndSet(motionDistance / distance, x, y, x1, y1, x2, y2, toX, toY, to);
142
- draw.BezierHelper.getPointAndSet(Math.max(0, motionDistance - 0.1) / distance, x, y, x1, y1, x2, y2, toX, toY, tempFrom);
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
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.cut(path, (motionDistance - total) / distance, x, y, x1, y1, x2, y2, toX, toY);
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));
@@ -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 = 0.5 * (1 + gaussNodes[i]);
11
- t2 = 0.5 * (1 - gaussNodes[i]);
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 * 0.5;
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
138
- motionDistance -= total;
139
- BezierHelper.getPointAndSet(motionDistance / distance, x, y, x1, y1, x2, y2, toX, toY, to);
140
- BezierHelper.getPointAndSet(Math.max(0, motionDistance - 0.1) / distance, x, y, x1, y1, x2, y2, toX, toY, tempFrom);
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
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.cut(path, (motionDistance - total) / distance, x, y, x1, y1, x2, y2, toX, toY);
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{PathCommandMap as t,MatrixHelper as e,PointHelper as o,UnitConvert as n,BezierHelper as a,decorateLeafAttr as r,attr as i,isNull as s,Transition as c,UI as h,LeafHelper as u,BranchHelper as l}from"@leafer-ui/draw";const f=[.1488743389,.4333953941,.6794095682,.8650633666,.9739065285],g=[.2955242247,.2692667193,.2190863625,.1494513491,.0666713443],{sqrt:m}=Math,_={getDistance(t,e,o,n,a,r,i,s){let c,h,u,l,_,P,p=0;for(let M=0;M<f.length;M++)c=.5*(1+f[M]),h=.5*(1-f[M]),u=d(c,t,o,a,i),l=d(c,e,n,r,s),_=d(h,t,o,a,i),P=d(h,e,n,r,s),p+=g[M]*(m(u*u+l*l)+m(_*_+P*P));return.5*p},getDerivative(t,e,o,n,a){const r=1-t;return 3*r*r*(o-e)+6*r*t*(n-o)+3*t*t*(a-n)},cut(e,o,n,a,r,i,s,c,h,u){const l=1-o,f=l*n+o*r,g=l*a+o*i,m=l*r+o*s,_=l*i+o*c,d=l*f+o*m,P=l*g+o*_,p=l*d+o*(l*m+o*(l*s+o*h)),M=l*P+o*(l*_+o*(l*c+o*u));e.push(t.C,f,g,d,P,p,M)}},{getDerivative:d}=_,{M:P,L:p,C:M,Z:y}=t,b={},x={},D={transform(t,e){let o,n=0;const a=t.length;for(;n<a;)switch(o=t[n],o){case P:case p:D.transformPoints(t,e,n,1),n+=3;break;case M:D.transformPoints(t,e,n,3),n+=7;break;case y:n+=1}},transformPoints(t,o,n,a){for(let r=n+1,i=r+2*a;r<i;r+=2)b.x=t[r],b.y=t[r+1],e.toOuterPoint(o,b),t[r]=b.x,t[r+1]=b.y},getMotionPathData(t){let e,n,a,r,i=0,s=[],c=0,h=0,u=0;const l=t.length;for(;c<l;){switch(r=t[c],r){case P:case p:n=t[c+1],a=t[c+2],e=r===p&&c>0?o.getDistanceFrom(h,u,n,a):0,h=n,u=a,c+=3;break;case M:n=t[c+5],a=t[c+6],e=_.getDistance(h,u,t[c+1],t[c+2],t[c+3],t[c+4],n,a),h=n,u=a,c+=7;break;case y:c+=1;default:e=0}s.push(e),i+=e}return{total:i,segments:s,data:t}},getDistancePoint(t,e){const{segments:r,data:i}=t;e=n.number(e,t.total);let s,c,h,u,l=0,f={},g=0,m=0,_=0,d=0;const b=i.length;for(;g<b;){switch(u=i[g],u){case P:case p:if(c=i[g+1],h=i[g+2],s=r[m],l+s>e||!t.total)return g||(_=c,d=h),x.x=_,x.y=d,f.x=c,f.y=h,o.getDistancePoint(x,f,e-l,!0),f.rotation=o.getAngle(x,f),f;_=c,d=h,g+=3;break;case M:if(c=i[g+5],h=i[g+6],s=r[m],l+s>e){const t=i[g+1],n=i[g+2],r=i[g+3],u=i[g+4];return e-=l,a.getPointAndSet(e/s,_,d,t,n,r,u,c,h,f),a.getPointAndSet(Math.max(0,e-.1)/s,_,d,t,n,r,u,c,h,x),f.rotation=o.getAngle(x,f),f}_=c,d=h,g+=7;break;case y:g+=1;default:s=0}m++,l+=s}return f},getDistancePath(t,e){const{segments:a,data:r}=t,i=[];e=n.number(e,t.total);let s,c,h,u,l=0,f={},g=0,m=0,d=0,b=0;const D=r.length;for(;g<D;){switch(u=r[g],u){case P:case p:if(c=r[g+1],h=r[g+2],s=a[m],l+s>e||!t.total)return g||(d=c,b=h),x.x=d,x.y=b,f.x=c,f.y=h,o.getDistancePoint(x,f,e-l,!0),i.push(u,f.x,f.y),i;d=c,b=h,g+=3,i.push(u,d,b);break;case M:const n=r[g+1],D=r[g+2],k=r[g+3],A=r[g+4];if(c=r[g+5],h=r[g+6],s=a[m],l+s>e)return _.cut(i,(e-l)/s,d,b,n,D,k,A,c,h),i;d=c,b=h,g+=7,i.push(u,n,D,k,A,c,h);break;case y:g+=1,i.push(u);default:s=0}m++,l+=s}return i}};function k(t){return r(t,(t=>i({set(e){this.__setAttr(t,e),this.__hasMotionPath=this.motionPath||!s(this.motion),this.__layout.matrixChanged||this.__layout.matrixChange()}})))}c.register("motion",(function(t,e,o,a){return t?"object"==typeof t&&(t=n.number(t,a.getMotionTotal())):t=0,e?"object"==typeof e&&(e=n.number(e,a.getMotionTotal())):e=0,c.number(t,e,o)})),c.register("motionRotation",(function(t,e,o){return c.number(t,e,o)}));const A=h.prototype,{updateMatrix:F,updateAllMatrix:C}=u,{updateBounds:v}=l;function w(t){const{motion:e,leaferIsCreated:o}=t;if(!s(e)){if(o&&(t.leafer.created=!1),t.motionPath){const o=T(t);o.total&&(t.__.__pathForRender=D.getDistancePath(o,e))}else t.set(t.getMotionPoint(e)),t.__hasAutoLayout||(t.isBranch?(C(t),v(t,t)):F(t));o&&(t.leafer.created=!0)}}function R(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 T(t){const e=t.__;return e.__pathForMotion?e.__pathForMotion:e.__pathForMotion=D.getMotionPathData(t.getPath(!0,!0))}k()(A,"motionPath"),k()(A,"motion"),k(!0)(A,"motionRotation"),A.getMotionPathData=function(){return T(R(this))},A.getMotionPoint=function(t){const o=R(this),n=T(o);if(!n.total)return{};const a=D.getDistancePoint(n,t);e.toOuterPoint(o.localTransform,a);const{motionRotation:r}=this;return!1===r?delete a.rotation:"number"==typeof r&&(a.rotation+=r),a},A.getMotionTotal=function(){return this.getMotionPathData().total},A.__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],s(t.motion)||t.__layout.matrixChanged||(o&&t!==this&&this.leafer.layouter.addExtra(t),w(t))}else w(this)};export{_ as HighBezierHelper,D as HighCurveHelper,k as motionPathType};
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};
@@ -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 = 0.5 * (1 + gaussNodes[i]);
13
- t2 = 0.5 * (1 - gaussNodes[i]);
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 * 0.5;
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
140
- motionDistance -= total;
141
- draw.BezierHelper.getPointAndSet(motionDistance / distance, x, y, x1, y1, x2, y2, toX, toY, to);
142
- draw.BezierHelper.getPointAndSet(Math.max(0, motionDistance - 0.1) / distance, x, y, x1, y1, x2, y2, toX, toY, tempFrom);
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4];
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.cut(path, (motionDistance - total) / distance, x, y, x1, y1, x2, y2, toX, toY);
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));
@@ -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,a={getDistance(t,a,i,s,c,h,l,u){let f,g,p,m,P,_,d=0;for(let M=0;M<e.length;M++)f=.5*(1+e[M]),g=.5*(1-e[M]),p=r(f,t,i,c,l),m=r(f,a,s,h,u),P=r(g,t,i,c,l),_=r(g,a,s,h,u),d+=o[M]*(n(p*p+m*m)+n(P*P+_*_));return.5*d},getDerivative(t,e,o,n,a){const r=1-t;return 3*r*r*(o-e)+6*r*t*(n-o)+3*t*t*(a-n)},cut(e,o,n,a,r,i,s,c,h,l){const u=1-o,f=u*n+o*r,g=u*a+o*i,p=u*r+o*s,m=u*i+o*c,P=u*f+o*p,_=u*g+o*m,d=u*P+o*(u*p+o*(u*s+o*h)),M=u*_+o*(u*m+o*(u*c+o*l));e.push(t.PathCommandMap.C,f,g,P,_,d,M)}},{getDerivative:r}=a,{M:i,L:s,C:c,Z:h}=t.PathCommandMap,l={},u={},f={transform(t,e){let o,n=0;const a=t.length;for(;n<a;)switch(o=t[n],o){case i:case s:f.transformPoints(t,e,n,1),n+=3;break;case c:f.transformPoints(t,e,n,3),n+=7;break;case h:n+=1}},transformPoints(e,o,n,a){for(let r=n+1,i=r+2*a;r<i;r+=2)l.x=e[r],l.y=e[r+1],t.MatrixHelper.toOuterPoint(o,l),e[r]=l.x,e[r+1]=l.y},getMotionPathData(e){let o,n,r,l,u=0,f=[],g=0,p=0,m=0;const P=e.length;for(;g<P;){switch(l=e[g],l){case i:case s:n=e[g+1],r=e[g+2],o=l===s&&g>0?t.PointHelper.getDistanceFrom(p,m,n,r):0,p=n,m=r,g+=3;break;case c:n=e[g+5],r=e[g+6],o=a.getDistance(p,m,e[g+1],e[g+2],e[g+3],e[g+4],n,r),p=n,m=r,g+=7;break;case h:g+=1;default:o=0}f.push(o),u+=o}return{total:u,segments:f,data:e}},getDistancePoint(e,o){const{segments:n,data:a}=e;o=t.UnitConvert.number(o,e.total);let r,l,f,g,p=0,m={},P=0,_=0,d=0,M=0;const x=a.length;for(;P<x;){switch(g=a[P],g){case i:case s:if(l=a[P+1],f=a[P+2],r=n[_],p+r>o||!e.total)return P||(d=l,M=f),u.x=d,u.y=M,m.x=l,m.y=f,t.PointHelper.getDistancePoint(u,m,o-p,!0),m.rotation=t.PointHelper.getAngle(u,m),m;d=l,M=f,P+=3;break;case c:if(l=a[P+5],f=a[P+6],r=n[_],p+r>o){const e=a[P+1],n=a[P+2],i=a[P+3],s=a[P+4];return o-=p,t.BezierHelper.getPointAndSet(o/r,d,M,e,n,i,s,l,f,m),t.BezierHelper.getPointAndSet(Math.max(0,o-.1)/r,d,M,e,n,i,s,l,f,u),m.rotation=t.PointHelper.getAngle(u,m),m}d=l,M=f,P+=7;break;case h:P+=1;default:r=0}_++,p+=r}return m},getDistancePath(e,o){const{segments:n,data:r}=e,l=[];o=t.UnitConvert.number(o,e.total);let f,g,p,m,P=0,_={},d=0,M=0,x=0,y=0;const b=r.length;for(;d<b;){switch(m=r[d],m){case i:case s:if(g=r[d+1],p=r[d+2],f=n[M],P+f>o||!e.total)return d||(x=g,y=p),u.x=x,u.y=y,_.x=g,_.y=p,t.PointHelper.getDistancePoint(u,_,o-P,!0),l.push(m,_.x,_.y),l;x=g,y=p,d+=3,l.push(m,x,y);break;case c:const b=r[d+1],D=r[d+2],H=r[d+3],C=r[d+4];if(g=r[d+5],p=r[d+6],f=n[M],P+f>o)return a.cut(l,(o-P)/f,x,y,b,D,H,C,g,p),l;x=g,y=p,d+=7,l.push(m,b,D,H,C,g,p);break;case h:d+=1,l.push(m);default:f=0}M++,P+=f}return l}};function g(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,a){return e?"object"==typeof e&&(e=t.UnitConvert.number(e,a.getMotionTotal())):e=0,o?"object"==typeof o&&(o=t.UnitConvert.number(o,a.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:m,updateAllMatrix:P}=t.LeafHelper,{updateBounds:_}=t.BranchHelper;function d(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=f.getDistancePath(t,o))}else e.set(e.getMotionPoint(o)),e.__hasAutoLayout||(e.isBranch?(P(e),_(e,e)):m(e));n&&(e.leafer.created=!0)}}function M(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=f.getMotionPathData(t.getPath(!0,!0))}g()(p,"motionPath"),g()(p,"motion"),g(!0)(p,"motionRotation"),p.getMotionPathData=function(){return x(M(this))},p.getMotionPoint=function(e){const o=M(this),n=x(o);if(!n.total)return{};const a=f.getDistancePoint(n,e);t.MatrixHelper.toOuterPoint(o.localTransform,a);const{motionRotation:r}=this;return!1===r?delete a.rotation:"number"==typeof r&&(a.rotation+=r),a},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 a=0;a<o.length;a++)e=o[a],t.isNull(e.motion)||e.__layout.matrixChanged||(n&&e!==this&&this.leafer.layouter.addExtra(e),d(e))}else d(this)},exports.HighBezierHelper=a,exports.HighCurveHelper=f,exports.motionPathType=g;
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;
@@ -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,r={getDistance(t,e,r,s,h,c,l,u){let f,g,m,p,P,_,d=0;for(let M=0;M<o.length;M++)f=.5*(1+o[M]),g=.5*(1-o[M]),m=i(f,t,r,h,l),p=i(f,e,s,c,u),P=i(g,t,r,h,l),_=i(g,e,s,c,u),d+=n[M]*(a(m*m+p*p)+a(P*P+_*_));return.5*d},getDerivative(t,e,o,n,a){const r=1-t;return 3*r*r*(o-e)+6*r*t*(n-o)+3*t*t*(a-n)},cut(t,o,n,a,r,i,s,h,c,l){const u=1-o,f=u*n+o*r,g=u*a+o*i,m=u*r+o*s,p=u*i+o*h,P=u*f+o*m,_=u*g+o*p,d=u*P+o*(u*m+o*(u*s+o*c)),M=u*_+o*(u*p+o*(u*h+o*l));t.push(e.PathCommandMap.C,f,g,P,_,d,M)}},{getDerivative:i}=r,{M:s,L:h,C:c,Z:l}=e.PathCommandMap,u={},f={},g={transform(t,e){let o,n=0;const a=t.length;for(;n<a;)switch(o=t[n],o){case s:case h:g.transformPoints(t,e,n,1),n+=3;break;case c:g.transformPoints(t,e,n,3),n+=7;break;case l:n+=1}},transformPoints(t,o,n,a){for(let r=n+1,i=r+2*a;r<i;r+=2)u.x=t[r],u.y=t[r+1],e.MatrixHelper.toOuterPoint(o,u),t[r]=u.x,t[r+1]=u.y},getMotionPathData(t){let o,n,a,i,u=0,f=[],g=0,m=0,p=0;const P=t.length;for(;g<P;){switch(i=t[g],i){case s:case h:n=t[g+1],a=t[g+2],o=i===h&&g>0?e.PointHelper.getDistanceFrom(m,p,n,a):0,m=n,p=a,g+=3;break;case c:n=t[g+5],a=t[g+6],o=r.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),u+=o}return{total:u,segments:f,data:t}},getDistancePoint(t,o){const{segments:n,data:a}=t;o=e.UnitConvert.number(o,t.total);let r,i,u,g,m=0,p={},P=0,_=0,d=0,M=0;const y=a.length;for(;P<y;){switch(g=a[P],g){case s:case h:if(i=a[P+1],u=a[P+2],r=n[_],m+r>o||!t.total)return P||(d=i,M=u),f.x=d,f.y=M,p.x=i,p.y=u,e.PointHelper.getDistancePoint(f,p,o-m,!0),p.rotation=e.PointHelper.getAngle(f,p),p;d=i,M=u,P+=3;break;case c:if(i=a[P+5],u=a[P+6],r=n[_],m+r>o){const t=a[P+1],n=a[P+2],s=a[P+3],h=a[P+4];return o-=m,e.BezierHelper.getPointAndSet(o/r,d,M,t,n,s,h,i,u,p),e.BezierHelper.getPointAndSet(Math.max(0,o-.1)/r,d,M,t,n,s,h,i,u,f),p.rotation=e.PointHelper.getAngle(f,p),p}d=i,M=u,P+=7;break;case l:P+=1;default:r=0}_++,m+=r}return p},getDistancePath(t,o){const{segments:n,data:a}=t,i=[];o=e.UnitConvert.number(o,t.total);let u,g,m,p,P=0,_={},d=0,M=0,y=0,b=0;const x=a.length;for(;d<x;){switch(p=a[d],p){case s:case h:if(g=a[d+1],m=a[d+2],u=n[M],P+u>o||!t.total)return d||(y=g,b=m),f.x=y,f.y=b,_.x=g,_.y=m,e.PointHelper.getDistancePoint(f,_,o-P,!0),i.push(p,_.x,_.y),i;y=g,b=m,d+=3,i.push(p,y,b);break;case c:const x=a[d+1],D=a[d+2],H=a[d+3],C=a[d+4];if(g=a[d+5],m=a[d+6],u=n[M],P+u>o)return r.cut(i,(o-P)/u,y,b,x,D,H,C,g,m),i;y=g,b=m,d+=7,i.push(p,x,D,H,C,g,m);break;case l:d+=1,i.push(p);default:u=0}M++,P+=u}return i}};function m(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:P,updateAllMatrix:_}=e.LeafHelper,{updateBounds:d}=e.BranchHelper;function M(t){const{motion:o,leaferIsCreated:n}=t;if(!e.isNull(o)){if(n&&(t.leafer.created=!1),t.motionPath){const e=b(t);e.total&&(t.__.__pathForRender=g.getDistancePath(e,o))}else t.set(t.getMotionPoint(o)),t.__hasAutoLayout||(t.isBranch?(_(t),d(t,t)):P(t));n&&(t.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 b(t){const e=t.__;return e.__pathForMotion?e.__pathForMotion:e.__pathForMotion=g.getMotionPathData(t.getPath(!0,!0))}return m()(p,"motionPath"),m()(p,"motion"),m(!0)(p,"motionRotation"),p.getMotionPathData=function(){return b(y(this))},p.getMotionPoint=function(t){const o=y(this),n=b(o);if(!n.total)return{};const a=g.getDistancePoint(n,t);e.MatrixHelper.toOuterPoint(o.localTransform,a);const{motionRotation:r}=this;return!1===r?delete a.rotation:"number"==typeof r&&(a.rotation+=r),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),M(t))}else M(this)},t.HighBezierHelper=r,t.HighCurveHelper=g,t.motionPathType=m,t}({},LeaferUI);
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.0.10",
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.0.10",
38
- "@leafer-ui/interface": "^1.0.10",
39
- "@leafer-in/interface": "^1.0.10"
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
  }
@@ -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 = 0.5 * (1 + gaussNodes[i])
17
- t2 = 0.5 * (1 - gaussNodes[i])
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 * 0.5
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
@@ -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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4]
124
- motionDistance -= total
125
- BezierHelper.getPointAndSet(motionDistance / distance, x, y, x1, y1, x2, y2, toX, toY, to)
126
- BezierHelper.getPointAndSet(Math.max(0, motionDistance - 0.1) / distance, x, y, x1, y1, x2, y2, toX, toY, tempFrom)
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
- const x1 = data[i + 1], y1 = data[i + 2], x2 = data[i + 3], y2 = data[i + 4]
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.cut(path, (motionDistance - total) / distance, x, y, x1, y1, x2, y2, toX, toY)
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