1 | import { cubicSubdivide } from '../core/curve.js';
|
2 | import Path from '../graphic/Path.js';
|
3 | import { defaults, map } from '../core/util.js';
|
4 | import { lerp } from '../core/vector.js';
|
5 | import { clonePath } from './path.js';
|
6 | import Transformable from '../core/Transformable.js';
|
7 | import { split } from './dividePath.js';
|
8 | import { pathToBezierCurves } from './convertPath.js';
|
9 | function alignSubpath(subpath1, subpath2) {
|
10 | var len1 = subpath1.length;
|
11 | var len2 = subpath2.length;
|
12 | if (len1 === len2) {
|
13 | return [subpath1, subpath2];
|
14 | }
|
15 | var tmpSegX = [];
|
16 | var tmpSegY = [];
|
17 | var shorterPath = len1 < len2 ? subpath1 : subpath2;
|
18 | var shorterLen = Math.min(len1, len2);
|
19 | var diff = Math.abs(len2 - len1) / 6;
|
20 | var shorterBezierCount = (shorterLen - 2) / 6;
|
21 | var eachCurveSubDivCount = Math.ceil(diff / shorterBezierCount) + 1;
|
22 | var newSubpath = [shorterPath[0], shorterPath[1]];
|
23 | var remained = diff;
|
24 | for (var i = 2; i < shorterLen;) {
|
25 | var x0 = shorterPath[i - 2];
|
26 | var y0 = shorterPath[i - 1];
|
27 | var x1 = shorterPath[i++];
|
28 | var y1 = shorterPath[i++];
|
29 | var x2 = shorterPath[i++];
|
30 | var y2 = shorterPath[i++];
|
31 | var x3 = shorterPath[i++];
|
32 | var y3 = shorterPath[i++];
|
33 | if (remained <= 0) {
|
34 | newSubpath.push(x1, y1, x2, y2, x3, y3);
|
35 | continue;
|
36 | }
|
37 | var actualSubDivCount = Math.min(remained, eachCurveSubDivCount - 1) + 1;
|
38 | for (var k = 1; k <= actualSubDivCount; k++) {
|
39 | var p = k / actualSubDivCount;
|
40 | cubicSubdivide(x0, x1, x2, x3, p, tmpSegX);
|
41 | cubicSubdivide(y0, y1, y2, y3, p, tmpSegY);
|
42 | x0 = tmpSegX[3];
|
43 | y0 = tmpSegY[3];
|
44 | newSubpath.push(tmpSegX[1], tmpSegY[1], tmpSegX[2], tmpSegY[2], x0, y0);
|
45 | x1 = tmpSegX[5];
|
46 | y1 = tmpSegY[5];
|
47 | x2 = tmpSegX[6];
|
48 | y2 = tmpSegY[6];
|
49 | }
|
50 | remained -= actualSubDivCount - 1;
|
51 | }
|
52 | return shorterPath === subpath1 ? [newSubpath, subpath2] : [subpath1, newSubpath];
|
53 | }
|
54 | function createSubpath(lastSubpathSubpath, otherSubpath) {
|
55 | var len = lastSubpathSubpath.length;
|
56 | var lastX = lastSubpathSubpath[len - 2];
|
57 | var lastY = lastSubpathSubpath[len - 1];
|
58 | var newSubpath = [];
|
59 | for (var i = 0; i < otherSubpath.length;) {
|
60 | newSubpath[i++] = lastX;
|
61 | newSubpath[i++] = lastY;
|
62 | }
|
63 | return newSubpath;
|
64 | }
|
65 | export function alignBezierCurves(array1, array2) {
|
66 | var _a;
|
67 | var lastSubpath1;
|
68 | var lastSubpath2;
|
69 | var newArray1 = [];
|
70 | var newArray2 = [];
|
71 | for (var i = 0; i < Math.max(array1.length, array2.length); i++) {
|
72 | var subpath1 = array1[i];
|
73 | var subpath2 = array2[i];
|
74 | var newSubpath1 = void 0;
|
75 | var newSubpath2 = void 0;
|
76 | if (!subpath1) {
|
77 | newSubpath1 = createSubpath(lastSubpath1 || subpath2, subpath2);
|
78 | newSubpath2 = subpath2;
|
79 | }
|
80 | else if (!subpath2) {
|
81 | newSubpath2 = createSubpath(lastSubpath2 || subpath1, subpath1);
|
82 | newSubpath1 = subpath1;
|
83 | }
|
84 | else {
|
85 | _a = alignSubpath(subpath1, subpath2), newSubpath1 = _a[0], newSubpath2 = _a[1];
|
86 | lastSubpath1 = newSubpath1;
|
87 | lastSubpath2 = newSubpath2;
|
88 | }
|
89 | newArray1.push(newSubpath1);
|
90 | newArray2.push(newSubpath2);
|
91 | }
|
92 | return [newArray1, newArray2];
|
93 | }
|
94 | export function centroid(array) {
|
95 | var signedArea = 0;
|
96 | var cx = 0;
|
97 | var cy = 0;
|
98 | var len = array.length;
|
99 | for (var i = 0, j = len - 2; i < len; j = i, i += 2) {
|
100 | var x0 = array[j];
|
101 | var y0 = array[j + 1];
|
102 | var x1 = array[i];
|
103 | var y1 = array[i + 1];
|
104 | var a = x0 * y1 - x1 * y0;
|
105 | signedArea += a;
|
106 | cx += (x0 + x1) * a;
|
107 | cy += (y0 + y1) * a;
|
108 | }
|
109 | if (signedArea === 0) {
|
110 | return [array[0] || 0, array[1] || 0];
|
111 | }
|
112 | return [cx / signedArea / 3, cy / signedArea / 3, signedArea];
|
113 | }
|
114 | function findBestRingOffset(fromSubBeziers, toSubBeziers, fromCp, toCp) {
|
115 | var bezierCount = (fromSubBeziers.length - 2) / 6;
|
116 | var bestScore = Infinity;
|
117 | var bestOffset = 0;
|
118 | var len = fromSubBeziers.length;
|
119 | var len2 = len - 2;
|
120 | for (var offset = 0; offset < bezierCount; offset++) {
|
121 | var cursorOffset = offset * 6;
|
122 | var score = 0;
|
123 | for (var k = 0; k < len; k += 2) {
|
124 | var idx = k === 0 ? cursorOffset : ((cursorOffset + k - 2) % len2 + 2);
|
125 | var x0 = fromSubBeziers[idx] - fromCp[0];
|
126 | var y0 = fromSubBeziers[idx + 1] - fromCp[1];
|
127 | var x1 = toSubBeziers[k] - toCp[0];
|
128 | var y1 = toSubBeziers[k + 1] - toCp[1];
|
129 | var dx = x1 - x0;
|
130 | var dy = y1 - y0;
|
131 | score += dx * dx + dy * dy;
|
132 | }
|
133 | if (score < bestScore) {
|
134 | bestScore = score;
|
135 | bestOffset = offset;
|
136 | }
|
137 | }
|
138 | return bestOffset;
|
139 | }
|
140 | function reverse(array) {
|
141 | var newArr = [];
|
142 | var len = array.length;
|
143 | for (var i = 0; i < len; i += 2) {
|
144 | newArr[i] = array[len - i - 2];
|
145 | newArr[i + 1] = array[len - i - 1];
|
146 | }
|
147 | return newArr;
|
148 | }
|
149 | function findBestMorphingRotation(fromArr, toArr, searchAngleIteration, searchAngleRange) {
|
150 | var result = [];
|
151 | var fromNeedsReverse;
|
152 | for (var i = 0; i < fromArr.length; i++) {
|
153 | var fromSubpathBezier = fromArr[i];
|
154 | var toSubpathBezier = toArr[i];
|
155 | var fromCp = centroid(fromSubpathBezier);
|
156 | var toCp = centroid(toSubpathBezier);
|
157 | if (fromNeedsReverse == null) {
|
158 | fromNeedsReverse = fromCp[2] < 0 !== toCp[2] < 0;
|
159 | }
|
160 | var newFromSubpathBezier = [];
|
161 | var newToSubpathBezier = [];
|
162 | var bestAngle = 0;
|
163 | var bestScore = Infinity;
|
164 | var tmpArr = [];
|
165 | var len = fromSubpathBezier.length;
|
166 | if (fromNeedsReverse) {
|
167 | fromSubpathBezier = reverse(fromSubpathBezier);
|
168 | }
|
169 | var offset = findBestRingOffset(fromSubpathBezier, toSubpathBezier, fromCp, toCp) * 6;
|
170 | var len2 = len - 2;
|
171 | for (var k = 0; k < len2; k += 2) {
|
172 | var idx = (offset + k) % len2 + 2;
|
173 | newFromSubpathBezier[k + 2] = fromSubpathBezier[idx] - fromCp[0];
|
174 | newFromSubpathBezier[k + 3] = fromSubpathBezier[idx + 1] - fromCp[1];
|
175 | }
|
176 | newFromSubpathBezier[0] = fromSubpathBezier[offset] - fromCp[0];
|
177 | newFromSubpathBezier[1] = fromSubpathBezier[offset + 1] - fromCp[1];
|
178 | if (searchAngleIteration > 0) {
|
179 | var step = searchAngleRange / searchAngleIteration;
|
180 | for (var angle = -searchAngleRange / 2; angle <= searchAngleRange / 2; angle += step) {
|
181 | var sa = Math.sin(angle);
|
182 | var ca = Math.cos(angle);
|
183 | var score = 0;
|
184 | for (var k = 0; k < fromSubpathBezier.length; k += 2) {
|
185 | var x0 = newFromSubpathBezier[k];
|
186 | var y0 = newFromSubpathBezier[k + 1];
|
187 | var x1 = toSubpathBezier[k] - toCp[0];
|
188 | var y1 = toSubpathBezier[k + 1] - toCp[1];
|
189 | var newX1 = x1 * ca - y1 * sa;
|
190 | var newY1 = x1 * sa + y1 * ca;
|
191 | tmpArr[k] = newX1;
|
192 | tmpArr[k + 1] = newY1;
|
193 | var dx = newX1 - x0;
|
194 | var dy = newY1 - y0;
|
195 | score += dx * dx + dy * dy;
|
196 | }
|
197 | if (score < bestScore) {
|
198 | bestScore = score;
|
199 | bestAngle = angle;
|
200 | for (var m = 0; m < tmpArr.length; m++) {
|
201 | newToSubpathBezier[m] = tmpArr[m];
|
202 | }
|
203 | }
|
204 | }
|
205 | }
|
206 | else {
|
207 | for (var i_1 = 0; i_1 < len; i_1 += 2) {
|
208 | newToSubpathBezier[i_1] = toSubpathBezier[i_1] - toCp[0];
|
209 | newToSubpathBezier[i_1 + 1] = toSubpathBezier[i_1 + 1] - toCp[1];
|
210 | }
|
211 | }
|
212 | result.push({
|
213 | from: newFromSubpathBezier,
|
214 | to: newToSubpathBezier,
|
215 | fromCp: fromCp,
|
216 | toCp: toCp,
|
217 | rotation: -bestAngle
|
218 | });
|
219 | }
|
220 | return result;
|
221 | }
|
222 | export function isCombineMorphing(path) {
|
223 | return path.__isCombineMorphing;
|
224 | }
|
225 | export function isMorphing(el) {
|
226 | return el.__morphT >= 0;
|
227 | }
|
228 | var SAVED_METHOD_PREFIX = '__mOriginal_';
|
229 | function saveAndModifyMethod(obj, methodName, modifiers) {
|
230 | var savedMethodName = SAVED_METHOD_PREFIX + methodName;
|
231 | var originalMethod = obj[savedMethodName] || obj[methodName];
|
232 | if (!obj[savedMethodName]) {
|
233 | obj[savedMethodName] = obj[methodName];
|
234 | }
|
235 | var replace = modifiers.replace;
|
236 | var after = modifiers.after;
|
237 | var before = modifiers.before;
|
238 | obj[methodName] = function () {
|
239 | var args = arguments;
|
240 | var res;
|
241 | before && before.apply(this, args);
|
242 | if (replace) {
|
243 | res = replace.apply(this, args);
|
244 | }
|
245 | else {
|
246 | res = originalMethod.apply(this, args);
|
247 | }
|
248 | after && after.apply(this, args);
|
249 | return res;
|
250 | };
|
251 | }
|
252 | function restoreMethod(obj, methodName) {
|
253 | var savedMethodName = SAVED_METHOD_PREFIX + methodName;
|
254 | if (obj[savedMethodName]) {
|
255 | obj[methodName] = obj[savedMethodName];
|
256 | obj[savedMethodName] = null;
|
257 | }
|
258 | }
|
259 | function applyTransformOnBeziers(bezierCurves, mm) {
|
260 | for (var i = 0; i < bezierCurves.length; i++) {
|
261 | var subBeziers = bezierCurves[i];
|
262 | for (var k = 0; k < subBeziers.length;) {
|
263 | var x = subBeziers[k];
|
264 | var y = subBeziers[k + 1];
|
265 | subBeziers[k++] = mm[0] * x + mm[2] * y + mm[4];
|
266 | subBeziers[k++] = mm[1] * x + mm[3] * y + mm[5];
|
267 | }
|
268 | }
|
269 | }
|
270 | function prepareMorphPath(fromPath, toPath) {
|
271 | var fromPathProxy = fromPath.getUpdatedPathProxy();
|
272 | var toPathProxy = toPath.getUpdatedPathProxy();
|
273 | var _a = alignBezierCurves(pathToBezierCurves(fromPathProxy), pathToBezierCurves(toPathProxy)), fromBezierCurves = _a[0], toBezierCurves = _a[1];
|
274 | var fromPathTransform = fromPath.getComputedTransform();
|
275 | var toPathTransform = toPath.getComputedTransform();
|
276 | function updateIdentityTransform() {
|
277 | this.transform = null;
|
278 | }
|
279 | fromPathTransform && applyTransformOnBeziers(fromBezierCurves, fromPathTransform);
|
280 | toPathTransform && applyTransformOnBeziers(toBezierCurves, toPathTransform);
|
281 | saveAndModifyMethod(toPath, 'updateTransform', { replace: updateIdentityTransform });
|
282 | toPath.transform = null;
|
283 | var morphingData = findBestMorphingRotation(fromBezierCurves, toBezierCurves, 10, Math.PI);
|
284 | var tmpArr = [];
|
285 | saveAndModifyMethod(toPath, 'buildPath', { replace: function (path) {
|
286 | var t = toPath.__morphT;
|
287 | var onet = 1 - t;
|
288 | var newCp = [];
|
289 | for (var i = 0; i < morphingData.length; i++) {
|
290 | var item = morphingData[i];
|
291 | var from = item.from;
|
292 | var to = item.to;
|
293 | var angle = item.rotation * t;
|
294 | var fromCp = item.fromCp;
|
295 | var toCp = item.toCp;
|
296 | var sa = Math.sin(angle);
|
297 | var ca = Math.cos(angle);
|
298 | lerp(newCp, fromCp, toCp, t);
|
299 | for (var m = 0; m < from.length; m += 2) {
|
300 | var x0_1 = from[m];
|
301 | var y0_1 = from[m + 1];
|
302 | var x1 = to[m];
|
303 | var y1 = to[m + 1];
|
304 | var x = x0_1 * onet + x1 * t;
|
305 | var y = y0_1 * onet + y1 * t;
|
306 | tmpArr[m] = (x * ca - y * sa) + newCp[0];
|
307 | tmpArr[m + 1] = (x * sa + y * ca) + newCp[1];
|
308 | }
|
309 | var x0 = tmpArr[0];
|
310 | var y0 = tmpArr[1];
|
311 | path.moveTo(x0, y0);
|
312 | for (var m = 2; m < from.length;) {
|
313 | var x1 = tmpArr[m++];
|
314 | var y1 = tmpArr[m++];
|
315 | var x2 = tmpArr[m++];
|
316 | var y2 = tmpArr[m++];
|
317 | var x3 = tmpArr[m++];
|
318 | var y3 = tmpArr[m++];
|
319 | if (x0 === x1 && y0 === y1 && x2 === x3 && y2 === y3) {
|
320 | path.lineTo(x3, y3);
|
321 | }
|
322 | else {
|
323 | path.bezierCurveTo(x1, y1, x2, y2, x3, y3);
|
324 | }
|
325 | x0 = x3;
|
326 | y0 = y3;
|
327 | }
|
328 | }
|
329 | } });
|
330 | }
|
331 | export function morphPath(fromPath, toPath, animationOpts) {
|
332 | if (!fromPath || !toPath) {
|
333 | return toPath;
|
334 | }
|
335 | var oldDone = animationOpts.done;
|
336 | var oldDuring = animationOpts.during;
|
337 | prepareMorphPath(fromPath, toPath);
|
338 | toPath.__morphT = 0;
|
339 | function restoreToPath() {
|
340 | restoreMethod(toPath, 'buildPath');
|
341 | restoreMethod(toPath, 'updateTransform');
|
342 | toPath.__morphT = -1;
|
343 | toPath.createPathProxy();
|
344 | toPath.dirtyShape();
|
345 | }
|
346 | toPath.animateTo({
|
347 | __morphT: 1
|
348 | }, defaults({
|
349 | during: function (p) {
|
350 | toPath.dirtyShape();
|
351 | oldDuring && oldDuring(p);
|
352 | },
|
353 | done: function () {
|
354 | restoreToPath();
|
355 | oldDone && oldDone();
|
356 | }
|
357 | }, animationOpts));
|
358 | return toPath;
|
359 | }
|
360 | function hilbert(x, y, minX, minY, maxX, maxY) {
|
361 | var bits = 16;
|
362 | x = (maxX === minX) ? 0 : Math.round(32767 * (x - minX) / (maxX - minX));
|
363 | y = (maxY === minY) ? 0 : Math.round(32767 * (y - minY) / (maxY - minY));
|
364 | var d = 0;
|
365 | var tmp;
|
366 | for (var s = (1 << bits) / 2; s > 0; s /= 2) {
|
367 | var rx = 0;
|
368 | var ry = 0;
|
369 | if ((x & s) > 0) {
|
370 | rx = 1;
|
371 | }
|
372 | if ((y & s) > 0) {
|
373 | ry = 1;
|
374 | }
|
375 | d += s * s * ((3 * rx) ^ ry);
|
376 | if (ry === 0) {
|
377 | if (rx === 1) {
|
378 | x = s - 1 - x;
|
379 | y = s - 1 - y;
|
380 | }
|
381 | tmp = x;
|
382 | x = y;
|
383 | y = tmp;
|
384 | }
|
385 | }
|
386 | return d;
|
387 | }
|
388 | function sortPaths(pathList) {
|
389 | var xMin = Infinity;
|
390 | var yMin = Infinity;
|
391 | var xMax = -Infinity;
|
392 | var yMax = -Infinity;
|
393 | var cps = map(pathList, function (path) {
|
394 | var rect = path.getBoundingRect();
|
395 | var m = path.getComputedTransform();
|
396 | var x = rect.x + rect.width / 2 + (m ? m[4] : 0);
|
397 | var y = rect.y + rect.height / 2 + (m ? m[5] : 0);
|
398 | xMin = Math.min(x, xMin);
|
399 | yMin = Math.min(y, yMin);
|
400 | xMax = Math.max(x, xMax);
|
401 | yMax = Math.max(y, yMax);
|
402 | return [x, y];
|
403 | });
|
404 | var items = map(cps, function (cp, idx) {
|
405 | return {
|
406 | cp: cp,
|
407 | z: hilbert(cp[0], cp[1], xMin, yMin, xMax, yMax),
|
408 | path: pathList[idx]
|
409 | };
|
410 | });
|
411 | return items.sort(function (a, b) { return a.z - b.z; }).map(function (item) { return item.path; });
|
412 | }
|
413 | ;
|
414 | function defaultDividePath(param) {
|
415 | return split(param.path, param.count);
|
416 | }
|
417 | function createEmptyReturn() {
|
418 | return {
|
419 | fromIndividuals: [],
|
420 | toIndividuals: [],
|
421 | count: 0
|
422 | };
|
423 | }
|
424 | export function combineMorph(fromList, toPath, animationOpts) {
|
425 | var fromPathList = [];
|
426 | function addFromPath(fromList) {
|
427 | for (var i = 0; i < fromList.length; i++) {
|
428 | var from = fromList[i];
|
429 | if (isCombineMorphing(from)) {
|
430 | addFromPath(from.childrenRef());
|
431 | }
|
432 | else if (from instanceof Path) {
|
433 | fromPathList.push(from);
|
434 | }
|
435 | }
|
436 | }
|
437 | addFromPath(fromList);
|
438 | var separateCount = fromPathList.length;
|
439 | if (!separateCount) {
|
440 | return createEmptyReturn();
|
441 | }
|
442 | var dividePath = animationOpts.dividePath || defaultDividePath;
|
443 | var toSubPathList = dividePath({
|
444 | path: toPath, count: separateCount
|
445 | });
|
446 | if (toSubPathList.length !== separateCount) {
|
447 | console.error('Invalid morphing: unmatched splitted path');
|
448 | return createEmptyReturn();
|
449 | }
|
450 | fromPathList = sortPaths(fromPathList);
|
451 | toSubPathList = sortPaths(toSubPathList);
|
452 | var oldDone = animationOpts.done;
|
453 | var oldDuring = animationOpts.during;
|
454 | var individualDelay = animationOpts.individualDelay;
|
455 | var identityTransform = new Transformable();
|
456 | for (var i = 0; i < separateCount; i++) {
|
457 | var from = fromPathList[i];
|
458 | var to = toSubPathList[i];
|
459 | to.parent = toPath;
|
460 | to.copyTransform(identityTransform);
|
461 | if (!individualDelay) {
|
462 | prepareMorphPath(from, to);
|
463 | }
|
464 | }
|
465 | toPath.__isCombineMorphing = true;
|
466 | toPath.childrenRef = function () {
|
467 | return toSubPathList;
|
468 | };
|
469 | function addToSubPathListToZr(zr) {
|
470 | for (var i = 0; i < toSubPathList.length; i++) {
|
471 | toSubPathList[i].addSelfToZr(zr);
|
472 | }
|
473 | }
|
474 | saveAndModifyMethod(toPath, 'addSelfToZr', {
|
475 | after: function (zr) {
|
476 | addToSubPathListToZr(zr);
|
477 | }
|
478 | });
|
479 | saveAndModifyMethod(toPath, 'removeSelfFromZr', {
|
480 | after: function (zr) {
|
481 | for (var i = 0; i < toSubPathList.length; i++) {
|
482 | toSubPathList[i].removeSelfFromZr(zr);
|
483 | }
|
484 | }
|
485 | });
|
486 | function restoreToPath() {
|
487 | toPath.__isCombineMorphing = false;
|
488 | toPath.__morphT = -1;
|
489 | toPath.childrenRef = null;
|
490 | restoreMethod(toPath, 'addSelfToZr');
|
491 | restoreMethod(toPath, 'removeSelfFromZr');
|
492 | }
|
493 | var toLen = toSubPathList.length;
|
494 | if (individualDelay) {
|
495 | var animating_1 = toLen;
|
496 | var eachDone = function () {
|
497 | animating_1--;
|
498 | if (animating_1 === 0) {
|
499 | restoreToPath();
|
500 | oldDone && oldDone();
|
501 | }
|
502 | };
|
503 | for (var i = 0; i < toLen; i++) {
|
504 | var indivdualAnimationOpts = individualDelay ? defaults({
|
505 | delay: (animationOpts.delay || 0) + individualDelay(i, toLen, fromPathList[i], toSubPathList[i]),
|
506 | done: eachDone
|
507 | }, animationOpts) : animationOpts;
|
508 | morphPath(fromPathList[i], toSubPathList[i], indivdualAnimationOpts);
|
509 | }
|
510 | }
|
511 | else {
|
512 | toPath.__morphT = 0;
|
513 | toPath.animateTo({
|
514 | __morphT: 1
|
515 | }, defaults({
|
516 | during: function (p) {
|
517 | for (var i = 0; i < toLen; i++) {
|
518 | var child = toSubPathList[i];
|
519 | child.__morphT = toPath.__morphT;
|
520 | child.dirtyShape();
|
521 | }
|
522 | oldDuring && oldDuring(p);
|
523 | },
|
524 | done: function () {
|
525 | restoreToPath();
|
526 | for (var i = 0; i < fromList.length; i++) {
|
527 | restoreMethod(fromList[i], 'updateTransform');
|
528 | }
|
529 | oldDone && oldDone();
|
530 | }
|
531 | }, animationOpts));
|
532 | }
|
533 | if (toPath.__zr) {
|
534 | addToSubPathListToZr(toPath.__zr);
|
535 | }
|
536 | return {
|
537 | fromIndividuals: fromPathList,
|
538 | toIndividuals: toSubPathList,
|
539 | count: toLen
|
540 | };
|
541 | }
|
542 | export function separateMorph(fromPath, toPathList, animationOpts) {
|
543 | var toLen = toPathList.length;
|
544 | var fromPathList = [];
|
545 | var dividePath = animationOpts.dividePath || defaultDividePath;
|
546 | function addFromPath(fromList) {
|
547 | for (var i = 0; i < fromList.length; i++) {
|
548 | var from = fromList[i];
|
549 | if (isCombineMorphing(from)) {
|
550 | addFromPath(from.childrenRef());
|
551 | }
|
552 | else if (from instanceof Path) {
|
553 | fromPathList.push(from);
|
554 | }
|
555 | }
|
556 | }
|
557 | if (isCombineMorphing(fromPath)) {
|
558 | addFromPath(fromPath.childrenRef());
|
559 | var fromLen = fromPathList.length;
|
560 | if (fromLen < toLen) {
|
561 | var k = 0;
|
562 | for (var i = fromLen; i < toLen; i++) {
|
563 | fromPathList.push(clonePath(fromPathList[k++ % fromLen]));
|
564 | }
|
565 | }
|
566 | fromPathList.length = toLen;
|
567 | }
|
568 | else {
|
569 | fromPathList = dividePath({ path: fromPath, count: toLen });
|
570 | var fromPathTransform = fromPath.getComputedTransform();
|
571 | for (var i = 0; i < fromPathList.length; i++) {
|
572 | fromPathList[i].setLocalTransform(fromPathTransform);
|
573 | }
|
574 | if (fromPathList.length !== toLen) {
|
575 | console.error('Invalid morphing: unmatched splitted path');
|
576 | return createEmptyReturn();
|
577 | }
|
578 | }
|
579 | fromPathList = sortPaths(fromPathList);
|
580 | toPathList = sortPaths(toPathList);
|
581 | var individualDelay = animationOpts.individualDelay;
|
582 | for (var i = 0; i < toLen; i++) {
|
583 | var indivdualAnimationOpts = individualDelay ? defaults({
|
584 | delay: (animationOpts.delay || 0) + individualDelay(i, toLen, fromPathList[i], toPathList[i])
|
585 | }, animationOpts) : animationOpts;
|
586 | morphPath(fromPathList[i], toPathList[i], indivdualAnimationOpts);
|
587 | }
|
588 | return {
|
589 | fromIndividuals: fromPathList,
|
590 | toIndividuals: toPathList,
|
591 | count: toPathList.length
|
592 | };
|
593 | }
|
594 | export { split as defaultDividePath };
|