| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.Morphing = void 0;
- const g_1 = require("@antv/g");
- const helper_1 = require("../utils/helper");
- const utils_1 = require("./utils");
- function localBBoxOf(shape) {
- const { min, max } = shape.getLocalBounds();
- const [x0, y0] = min;
- const [x1, y1] = max;
- const height = y1 - y0;
- const width = x1 - x0;
- return [x0, y0, width, height];
- }
- function d(bbox) {
- const [x, y, width, height] = bbox;
- return `
- M ${x} ${y}
- L ${x + width} ${y}
- L ${x + width} ${y + height}
- L ${x} ${y + height}
- Z
- `;
- }
- function pack(shape, count) {
- const [x0, y0, width, height] = localBBoxOf(shape);
- const aspect = height / width;
- const col = Math.ceil(Math.sqrt(count / aspect));
- const row = Math.ceil(count / col);
- const B = [];
- const h = height / row;
- let j = 0;
- let n = count;
- while (n > 0) {
- const c = Math.min(n, col);
- const w = width / c;
- for (let i = 0; i < c; i++) {
- const x = x0 + i * w;
- const y = y0 + j * h;
- B.push(d([x, y, w, h]));
- }
- n -= c;
- j += 1;
- }
- return B;
- }
- function normalizeSplit(split = 'pack') {
- if (typeof split == 'function')
- return split;
- return pack;
- }
- /**
- * Translate and scale.
- */
- function shapeToShape(from, to, timeEffect) {
- const [x0, y0, w0, h0] = localBBoxOf(from);
- const { transform: fromTransform } = from.style;
- const { transform: toTransform } = to.style;
- // Replace first to get right bbox after mounting.
- replaceChild(to, from);
- // Apply translate and scale transform.
- const [x1, y1, w1, h1] = localBBoxOf(to);
- const dx = x0 - x1;
- const dy = y0 - y1;
- const sx = w0 / w1;
- const sy = h0 / h1;
- const keyframes = [
- Object.assign({ transform: `${fromTransform ? fromTransform + ' ' : ''}translate(${dx}, ${dy}) scale(${sx}, ${sy})` }, (0, utils_1.attributeOf)(from, utils_1.attributeKeys)),
- Object.assign({ transform: `${toTransform ? toTransform + ' ' : ''}translate(0, 0) scale(1, 1)` }, (0, utils_1.attributeOf)(to, utils_1.attributeKeys)),
- ];
- const animation = to.animate(keyframes, timeEffect);
- return animation;
- }
- /**
- * Replace object and copy className and __data__
- */
- function replaceChild(newChild, oldChild) {
- newChild['__data__'] = oldChild['__data__'];
- newChild.className = oldChild.className;
- oldChild.parentNode.replaceChild(newChild, oldChild);
- }
- /**
- * Replace element with a path shape.
- */
- function maybePath(node, d) {
- const { nodeName } = node;
- if (nodeName === 'path')
- return node;
- const path = new g_1.Path({
- style: Object.assign(Object.assign({}, (0, utils_1.attributeOf)(node, utils_1.attributeKeys)), { d }),
- });
- replaceChild(path, node);
- return path;
- }
- function hasUniqueString(search, pattern) {
- const first = search.indexOf(pattern);
- const last = search.lastIndexOf(pattern);
- return first === last;
- }
- // Path definition with multiple m and M command has sub path.
- // eg. 'M10,10...M20,20', 'm10,10...m20,20'
- function hasSubPath(path) {
- return !hasUniqueString(path, 'm') || !hasUniqueString(path, 'M');
- }
- function shape2path(shape) {
- const path = (0, g_1.convertToPath)(shape);
- if (!path)
- return;
- // Path definition with sub path can't do path morphing animation,
- // so skip this kind of path.
- if (hasSubPath(path))
- return;
- return path;
- }
- function oneToOne(shape, from, to, timeEffect) {
- // If the nodeTypes of from and to are equal,
- // or non of them can convert to path,
- // the apply shape to shape animation.
- const { nodeName: fromName } = from;
- const { nodeName: toName } = to;
- const fromPath = shape2path(from);
- const toPath = shape2path(to);
- const isSameNodes = fromName === toName && fromName !== 'path';
- const hasNonPathNode = fromPath === undefined || toPath === undefined;
- if (isSameNodes || hasNonPathNode)
- return shapeToShape(from, to, timeEffect);
- const pathShape = maybePath(shape, fromPath);
- // Convert Path will take transform, anchor, etc into account,
- // so there is no need to specify these attributes in keyframes.
- const keyframes = [
- Object.assign({ path: fromPath }, (0, utils_1.attributeOf)(from, utils_1.attributeKeys)),
- Object.assign({ path: toPath }, (0, utils_1.attributeOf)(to, utils_1.attributeKeys)),
- ];
- const animation = pathShape.animate(keyframes, timeEffect);
- animation.onfinish = () => {
- (0, helper_1.copyAttributes)(pathShape, to);
- };
- // Remove transform because it already applied in path
- // converted by convertToPath.
- // @todo Remove this scale(1, 1)
- pathShape.style.transform = 'scale(1, 1)';
- pathShape.style.transform = 'none';
- return animation;
- }
- function oneToMultiple(from, to, timeEffect, split) {
- // Hide the shape to be split before being removing.
- from.style.visibility = 'hidden';
- const D = split(from, to.length);
- return to.map((shape, i) => {
- const path = new g_1.Path({
- style: Object.assign({ path: D[i] }, (0, utils_1.attributeOf)(from, utils_1.attributeKeys)),
- });
- return oneToOne(shape, path, shape, timeEffect);
- });
- }
- function multipleToOne(from, to, timeEffect, split) {
- const D = split(to, from.length);
- const { fillOpacity = 1, strokeOpacity = 1, opacity = 1 } = to.style;
- const keyframes = [
- { fillOpacity: 0, strokeOpacity: 0, opacity: 0 },
- { fillOpacity: 0, strokeOpacity: 0, opacity: 0, offset: 0.99 },
- {
- fillOpacity,
- strokeOpacity,
- opacity,
- },
- ];
- const animation = to.animate(keyframes, timeEffect);
- const animations = from.map((shape, i) => {
- const path = new g_1.Path({
- style: {
- path: D[i],
- fill: to.style.fill,
- },
- });
- return oneToOne(shape, shape, path, timeEffect);
- });
- return [...animations, animation];
- }
- /**
- * Morphing animations.
- * @todo Support more split function.
- */
- const Morphing = (options) => {
- return (from, to, value, coordinate, defaults) => {
- const split = normalizeSplit(options.split);
- const timeEffect = (0, utils_1.effectTiming)(defaults, value, options);
- const { length: fl } = from;
- const { length: tl } = to;
- if ((fl === 1 && tl === 1) || (fl > 1 && tl > 1)) {
- const [f] = from;
- const [t] = to;
- return oneToOne(f, f, t, timeEffect);
- }
- if (fl === 1 && tl > 1) {
- const [f] = from;
- return oneToMultiple(f, to, timeEffect, split);
- }
- if (fl > 1 && tl === 1) {
- const [t] = to;
- return multipleToOne(from, t, timeEffect, split);
- }
- return null;
- };
- };
- exports.Morphing = Morphing;
- exports.Morphing.props = {};
- //# sourceMappingURL=morphing.js.map
|