UNPKG

@visactor/vrender-core

Version:
292 lines (276 loc) 17.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.multiToOneMorph = exports.splitGraphic = exports.cloneGraphic = exports.MultiToOneMorphingPath = exports.oneToMultiMorph = exports.morphPath = exports.MorphingPath = void 0; const split_path_1 = require("./../common/split-path"), custom_path2d_1 = require("../common/custom-path2d"), animate_1 = require("./animate"), morphing_utils_1 = require("../common/morphing-utils"), application_1 = require("../application"), vutils_1 = require("@visactor/vutils"), interpolate_1 = require("../color-string/interpolate"), color_string_1 = require("../color-string"), config_1 = require("./config"), utils_1 = require("../common/utils"), enums_1 = require("../common/enums"), interpolateOtherAttrs = (attrs, out, ratio) => { attrs.forEach((entry => { if (Number.isFinite(entry.to)) out[entry.key] = entry.from + (entry.to - entry.from) * ratio; else if ("fill" === entry.key || "stroke" === entry.key) { const color = (0, interpolate_1.interpolateColor)(entry.from, entry.to, ratio, !1); color && (out[entry.key] = color); } })); }, interpolateMorphingData = (morphingData, path, ratio) => { const tmpArr = [], newCp = []; path.clear(); for (let i = 0; i < morphingData.length; i++) { const item = morphingData[i], from = item.from, to = item.to, angle = item.rotation * ratio, fromCp = item.fromCp, toCp = item.toCp, sa = Math.sin(angle), ca = Math.cos(angle); newCp[0] = fromCp[0] + (toCp[0] - fromCp[0]) * ratio, newCp[1] = fromCp[1] + (toCp[1] - fromCp[1]) * ratio; for (let m = 0; m < from.length; m += 2) { const x0 = from[m], y0 = from[m + 1], x = x0 * (1 - ratio) + to[m] * ratio, y = y0 * (1 - ratio) + to[m + 1] * ratio; tmpArr[m] = x * ca - y * sa + newCp[0], tmpArr[m + 1] = x * sa + y * ca + newCp[1]; } let x0 = tmpArr[0], y0 = tmpArr[1]; path.moveTo(x0, y0); for (let m = 2; m < from.length; m += 6) { const x1 = tmpArr[m], y1 = tmpArr[m + 1], x2 = tmpArr[m + 2], y2 = tmpArr[m + 3], x3 = tmpArr[m + 4], y3 = tmpArr[m + 5]; x0 === x1 && y0 === y1 && x2 === x3 && y2 === y3 ? path.lineTo(x3, y3) : path.bezierCurveTo(x1, y1, x2, y2, x3, y3), x0 = x3, y0 = y3; } } }, parseMorphingData = (fromPath, toPath, config) => { const fromBezier = fromPath ? (0, morphing_utils_1.pathToBezierCurves)(fromPath) : [], toBezier = (0, morphing_utils_1.pathToBezierCurves)(toPath); config && fromBezier && (config.fromTransform && (0, morphing_utils_1.applyTransformOnBezierCurves)(fromBezier, config.fromTransform.clone().getInverse()), (0, morphing_utils_1.applyTransformOnBezierCurves)(fromBezier, config.toTransfrom)); const [fromBezierCurves, toBezierCurves] = (0, morphing_utils_1.alignBezierCurves)(fromBezier, toBezier); return fromPath ? (0, morphing_utils_1.findBestMorphingRotation)(fromBezierCurves, toBezierCurves, 10, Math.PI) : toBezierCurves.map(((to, index) => ({ from: fromBezierCurves[index], to: to, fromCp: [ 0, 0 ], toCp: [ 0, 0 ], rotation: 0 }))); }, validateOtherAttrs = [ "fill", "fillOpacity", "shadowBlur", "shadowColor", "shadowOffsetX", "shadowOffsetY", "stroke", "strokeOpacity", "lineDashOffset" ], parseOtherAnimateAttrs = (fromAttrs, toAttrs) => { if (!fromAttrs || !toAttrs) return null; const res = []; let hasAttr = !1; return Object.keys(fromAttrs).forEach((fromKey => { if (!validateOtherAttrs.includes(fromKey)) return; const toValue = toAttrs[fromKey]; (0, vutils_1.isNil)(toValue) || (0, vutils_1.isNil)(fromAttrs[fromKey]) || toValue === fromAttrs[fromKey] || ("fill" === fromKey || "stroke" === fromKey ? res.push({ from: "string" == typeof fromAttrs[fromKey] ? color_string_1.ColorStore.Get(fromAttrs[fromKey], color_string_1.ColorType.Color255) : fromAttrs[fromKey], to: "string" == typeof toValue ? color_string_1.ColorStore.Get(toValue, color_string_1.ColorType.Color255) : toValue, key: fromKey }) : res.push({ from: fromAttrs[fromKey], to: toValue, key: fromKey }), hasAttr = !0); })), hasAttr ? res : null; }; class MorphingPath extends animate_1.ACustomAnimate { constructor(config, duration, easing) { super(0, 1, duration, easing), this.morphingData = config.morphingData, this.otherAttrs = config.otherAttrs, this.saveOnEnd = config.saveOnEnd; } getEndProps() { return {}; } onBind() { this.target.createPathProxy(), this.onUpdate(!1, 0, this.target.attribute); } onEnd() {} onUpdate(end, ratio, out) { const target = this.target, pathProxy = "function" == typeof target.pathProxy ? target.pathProxy(target.attribute) : target.pathProxy; interpolateMorphingData(this.morphingData, pathProxy, ratio), this.otherAttrs && this.otherAttrs.length && interpolateOtherAttrs(this.otherAttrs, out, ratio), end && !this.saveOnEnd && (this.target.pathProxy = null); } } exports.MorphingPath = MorphingPath; const morphPath = (fromGraphic, toGraphic, animationConfig, fromGraphicTransform) => { var _a, _b, _c; if (fromGraphic && (!fromGraphic.valid || !fromGraphic.toCustomPath)) return __DEV__ && console.error(fromGraphic, " is not validate"), null; if (!toGraphic.valid || !toGraphic.toCustomPath) return __DEV__ && console.error(toGraphic, " is not validate"), null; let fromTransform = null == fromGraphic ? void 0 : fromGraphic.globalTransMatrix; fromGraphicTransform && fromTransform && (fromTransform = fromGraphicTransform.clone().multiply(fromTransform.a, fromTransform.b, fromTransform.c, fromTransform.d, fromTransform.e, fromTransform.f)); const morphingData = parseMorphingData(null === (_a = null == fromGraphic ? void 0 : fromGraphic.toCustomPath) || void 0 === _a ? void 0 : _a.call(fromGraphic), toGraphic.toCustomPath(), { fromTransform: fromTransform, toTransfrom: toGraphic.globalTransMatrix }), attrs = parseOtherAnimateAttrs(null == fromGraphic ? void 0 : fromGraphic.attribute, toGraphic.attribute), animate = toGraphic.animate(animationConfig); return (null == animationConfig ? void 0 : animationConfig.delay) && animate.wait(animationConfig.delay), animate.play(new MorphingPath({ morphingData: morphingData, otherAttrs: attrs }, null !== (_b = null == animationConfig ? void 0 : animationConfig.duration) && void 0 !== _b ? _b : config_1.DefaultMorphingAnimateConfig.duration, null !== (_c = null == animationConfig ? void 0 : animationConfig.easing) && void 0 !== _c ? _c : config_1.DefaultMorphingAnimateConfig.easing)), animate; }; exports.morphPath = morphPath; const oneToMultiMorph = (fromGraphic, toGraphics, animationConfig) => { var _a; const validateToGraphics = toGraphics.filter((graphic => graphic && graphic.toCustomPath && graphic.valid)); validateToGraphics.length || __DEV__ && console.error(validateToGraphics, " is not validate"), fromGraphic.valid && fromGraphic.toCustomPath || __DEV__ && console.error(fromGraphic, " is not validate"); const childGraphics = ("clone" === (null == animationConfig ? void 0 : animationConfig.splitPath) ? exports.cloneGraphic : null !== (_a = null == animationConfig ? void 0 : animationConfig.splitPath) && void 0 !== _a ? _a : exports.splitGraphic)(fromGraphic, validateToGraphics.length, !1), oldOnEnd = null == animationConfig ? void 0 : animationConfig.onEnd; let count = validateToGraphics.length; const onEachEnd = () => { count--, 0 === count && oldOnEnd && oldOnEnd(); }; validateToGraphics.forEach(((toChild, index) => { var _a; const fromChild = childGraphics[index], delay = (null !== (_a = null == animationConfig ? void 0 : animationConfig.delay) && void 0 !== _a ? _a : 0) + ((null == animationConfig ? void 0 : animationConfig.individualDelay) ? animationConfig.individualDelay(index, validateToGraphics.length, fromChild, toChild) : 0); (0, exports.morphPath)(fromChild, toChild, Object.assign({}, animationConfig, { onEnd: onEachEnd, delay: delay }), fromGraphic.globalTransMatrix); })); }; exports.oneToMultiMorph = oneToMultiMorph; class MultiToOneMorphingPath extends animate_1.ACustomAnimate { constructor(config, duration, easing) { super(0, 1, duration, easing), this.morphingData = config.morphingData, this.otherAttrs = config.otherAttrs; } getEndProps() { return {}; } onBind() { this.addPathProxy(); } addPathProxy() { this.target.shadowRoot.forEachChildren((child => { child.createPathProxy(); })), this.onUpdate(!1, 0, this.target.attribute); } clearPathProxy() { this.target.shadowRoot.forEachChildren((child => { child.pathProxy = null; })); } onEnd() {} onUpdate(end, ratio, out) { this.target.shadowRoot.forEachChildren(((child, index) => { var _a; interpolateMorphingData(this.morphingData[index], "function" == typeof child.pathProxy ? child.pathProxy(child.attribute) : child.pathProxy, ratio), (null === (_a = this.otherAttrs) || void 0 === _a ? void 0 : _a[index]) && this.otherAttrs[index].length && interpolateOtherAttrs(this.otherAttrs[index], child.attribute, ratio); })), end && (this.clearPathProxy(), this.morphingData = null); } } exports.MultiToOneMorphingPath = MultiToOneMorphingPath; const parseShadowChildAttrs = graphicAttrs => { const attrs = {}; return Object.keys(graphicAttrs).forEach((key => { (0, utils_1.isTransformKey)(key) || (attrs[key] = graphicAttrs[key]); })), attrs; }, appendShadowChildrenToGraphic = (graphic, children, count) => { const childAttrs = parseShadowChildAttrs(graphic.attribute), shadowRoot = graphic.attachShadow(); if (children.length) shadowRoot.setTheme({ [children[0].type]: childAttrs }), children.forEach((element => { element.setAttributes({ pickable: !1 }), shadowRoot.appendChild(element); })); else { const box = graphic.AABBBounds, width = box.width(), height = box.height(); shadowRoot.setTheme({ rect: childAttrs }), new Array(count).fill(0).forEach((el => { const child = application_1.application.graphicService.creator.rect({ x: 0, y: 0, width: width, height: height, pickable: !1 }); shadowRoot.appendChild(child), children.push(child); })); } }, cloneGraphic = (graphic, count, needAppend) => { const children = [], childAttrs = needAppend ? null : parseShadowChildAttrs(graphic.attribute), path = graphic.toCustomPath(); for (let i = 0; i < count; i++) { const element = { path: (new custom_path2d_1.CustomPath2D).fromCustomPath2D(path) }; children.push(application_1.application.graphicService.creator.path(needAppend ? element : Object.assign({}, childAttrs, element))); } return needAppend && appendShadowChildrenToGraphic(graphic, children, count), children; }; exports.cloneGraphic = cloneGraphic; const splitGraphic = (graphic, count, needAppend) => { const children = [], childAttrs = needAppend ? null : parseShadowChildAttrs(graphic.attribute); if ("rect" === graphic.type) { (0, split_path_1.splitRect)(graphic, count).forEach((element => { children.push(application_1.application.graphicService.creator.rect(needAppend ? element : Object.assign({}, childAttrs, element))); })); } else if ("arc" === graphic.type) { (0, split_path_1.splitArc)(graphic, count).forEach((element => { children.push(application_1.application.graphicService.creator.arc(needAppend ? element : Object.assign({}, childAttrs, element))); })); } else if ("circle" === graphic.type) { (0, split_path_1.splitCircle)(graphic, count).forEach((element => { children.push(application_1.application.graphicService.creator.arc(needAppend ? element : Object.assign({}, childAttrs, element))); })); } else if ("line" === graphic.type) { const childrenAttrs = (0, split_path_1.splitLine)(graphic, count), defaultSymbol = { size: 10, symbolType: "circle" }; childrenAttrs.forEach((element => { children.push(application_1.application.graphicService.creator.symbol(needAppend ? Object.assign({}, element, defaultSymbol) : Object.assign({}, childAttrs, element, defaultSymbol))); })); } else if ("polygon" === graphic.type) { (0, split_path_1.splitPolygon)(graphic, count).forEach((element => { children.push(application_1.application.graphicService.creator.polygon(needAppend ? element : Object.assign({}, childAttrs, element))); })); } else if ("area" === graphic.type) { (0, split_path_1.splitArea)(graphic, count).forEach((element => { children.push(application_1.application.graphicService.creator.polygon(needAppend ? element : Object.assign({}, childAttrs, element))); })); } else if ("path" === graphic.type) { (0, split_path_1.splitPath)(graphic, count).forEach((element => { "path" in element ? children.push(application_1.application.graphicService.creator.path(needAppend ? element : Object.assign({}, childAttrs, element))) : children.push(application_1.application.graphicService.creator.polygon(needAppend ? element : Object.assign({}, childAttrs, element))); })); } return needAppend && appendShadowChildrenToGraphic(graphic, children, count), children; }; exports.splitGraphic = splitGraphic; const multiToOneMorph = (fromGraphics, toGraphic, animationConfig) => { var _a, _b, _c; const validateFromGraphics = fromGraphics.filter((graphic => graphic.toCustomPath && graphic.valid)); validateFromGraphics.length || __DEV__ && console.error(fromGraphics, " is not validate"), toGraphic.valid && toGraphic.toCustomPath || __DEV__ && console.error(toGraphic, " is not validate"); const childGraphics = ("clone" === (null == animationConfig ? void 0 : animationConfig.splitPath) ? exports.cloneGraphic : null !== (_a = null == animationConfig ? void 0 : animationConfig.splitPath) && void 0 !== _a ? _a : exports.splitGraphic)(toGraphic, validateFromGraphics.length, !0), toAttrs = toGraphic.attribute; toGraphic.setAttribute("visible", !1); const morphingData = validateFromGraphics.map(((graphic, index) => parseMorphingData(graphic.toCustomPath(), childGraphics[index].toCustomPath(), { fromTransform: graphic.globalTransMatrix, toTransfrom: childGraphics[index].globalTransMatrix }))), otherAttrs = validateFromGraphics.map(((graphic, index) => parseOtherAnimateAttrs(graphic.attribute, toAttrs))); if (null == animationConfig ? void 0 : animationConfig.individualDelay) { const oldOnEnd = animationConfig.onEnd; let count = validateFromGraphics.length; const onEachEnd = () => { count--, 0 === count && (toGraphic.setAttributes({ visible: !0, ratio: null }, !1, { type: enums_1.AttributeUpdateType.ANIMATE_END }), toGraphic.detachShadow(), oldOnEnd && oldOnEnd()); }; childGraphics.forEach(((to, index) => { var _a, _b, _c; const delay = (null !== (_a = animationConfig.delay) && void 0 !== _a ? _a : 0) + animationConfig.individualDelay(index, validateFromGraphics.length, fromGraphics[index], to), animate = to.animate(Object.assign({}, animationConfig, { onEnd: onEachEnd })); animate.wait(delay), animate.play(new MorphingPath({ morphingData: morphingData[index], saveOnEnd: !0, otherAttrs: otherAttrs[index] }, null !== (_b = animationConfig.duration) && void 0 !== _b ? _b : config_1.DefaultMorphingAnimateConfig.duration, null !== (_c = animationConfig.easing) && void 0 !== _c ? _c : config_1.DefaultMorphingAnimateConfig.easing)); })); } else { const oldOnEnd = null == animationConfig ? void 0 : animationConfig.onEnd, config = animationConfig ? Object.assign({}, animationConfig) : {}; config.onEnd = () => { toGraphic.setAttribute("visible", !0, !1, { type: enums_1.AttributeUpdateType.ANIMATE_END }), toGraphic.detachShadow(), oldOnEnd && oldOnEnd(); }; const animate = toGraphic.animate(config); (null == animationConfig ? void 0 : animationConfig.delay) && animate.wait(animationConfig.delay), animate.play(new MultiToOneMorphingPath({ morphingData: morphingData, otherAttrs: otherAttrs }, null !== (_b = null == animationConfig ? void 0 : animationConfig.duration) && void 0 !== _b ? _b : config_1.DefaultMorphingAnimateConfig.duration, null !== (_c = null == animationConfig ? void 0 : animationConfig.easing) && void 0 !== _c ? _c : config_1.DefaultMorphingAnimateConfig.easing)); } }; exports.multiToOneMorph = multiToOneMorph; //# sourceMappingURL=morphing.js.map