"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var util_1 = require("@antv/util"); var d3Timer = require("d3-timer"); var d3_interpolate_1 = require("d3-interpolate"); // 目前整体动画只需要数值和数组的差值计算 var register_1 = require("./register"); var PathUtil = require("../util/path"); var color_1 = require("../util/color"); var IDENTITY_MATRIX = [1, 0, 0, 0, 1, 0, 0, 0, 1]; /** * 使用 ratio 进行插值计算来更新属性 * @param {IElement} shape 元素 * @param {Animation} animation 动画 * @param {number} ratio 比例 * @return {boolean} 动画是否执行完成 */ function _update(shape, animation, ratio) { var cProps = {}; // 此刻属性 var fromAttrs = animation.fromAttrs, toAttrs = animation.toAttrs; if (shape.destroyed) { return; } var interf; // 差值函数 for (var k in toAttrs) { if (!util_1.isEqual(fromAttrs[k], toAttrs[k])) { if (k === 'path') { var toPath = toAttrs[k]; var fromPath = fromAttrs[k]; if (toPath.length > fromPath.length) { toPath = PathUtil.parsePathString(toAttrs[k]); // 终点状态 fromPath = PathUtil.parsePathString(fromAttrs[k]); // 起始状态 fromPath = PathUtil.fillPathByDiff(fromPath, toPath); fromPath = PathUtil.formatPath(fromPath, toPath); animation.fromAttrs.path = fromPath; animation.toAttrs.path = toPath; } else if (!animation.pathFormatted) { toPath = PathUtil.parsePathString(toAttrs[k]); fromPath = PathUtil.parsePathString(fromAttrs[k]); fromPath = PathUtil.formatPath(fromPath, toPath); animation.fromAttrs.path = fromPath; animation.toAttrs.path = toPath; animation.pathFormatted = true; } cProps[k] = []; for (var i = 0; i < toPath.length; i++) { var toPathPoint = toPath[i]; var fromPathPoint = fromPath[i]; var cPathPoint = []; for (var j = 0; j < toPathPoint.length; j++) { if (util_1.isNumber(toPathPoint[j]) && fromPathPoint && util_1.isNumber(fromPathPoint[j])) { interf = d3_interpolate_1.interpolate(fromPathPoint[j], toPathPoint[j]); cPathPoint.push(interf(ratio)); } else { cPathPoint.push(toPathPoint[j]); } } cProps[k].push(cPathPoint); } } else if (k === 'matrix') { /* 对矩阵进行插值时,需要保证矩阵不为空,为空则使用单位矩阵 TODO: 二维和三维场景下单位矩阵不同,之后 WebGL 版需要做进一步处理 */ var matrixFn = d3_interpolate_1.interpolateArray(fromAttrs[k] || IDENTITY_MATRIX, toAttrs[k] || IDENTITY_MATRIX); var currentMatrix = matrixFn(ratio); cProps[k] = currentMatrix; } else if (color_1.isColorProp(k) && color_1.isGradientColor(toAttrs[k])) { cProps[k] = toAttrs[k]; } else if (!util_1.isFunction(toAttrs[k])) { // 非函数类型的值才能做插值 interf = d3_interpolate_1.interpolate(fromAttrs[k], toAttrs[k]); cProps[k] = interf(ratio); } } } shape.attr(cProps); } /** * 根据自定义帧动画函数 onFrame 来更新属性 * @param {IElement} shape 元素 * @param {Animation} animation 动画 * @param {number} elapsed 动画执行时间(毫秒) * @return {boolean} 动画是否执行完成 */ function update(shape, animation, elapsed) { var startTime = animation.startTime, delay = animation.delay; // 如果还没有开始执行或暂停,先不更新 if (elapsed < startTime + delay || animation._paused) { return false; } var ratio; var duration = animation.duration; var easing = animation.easing; var easeFn = register_1.getEasing(easing); // 已执行时间 elapsed = elapsed - startTime - animation.delay; if (animation.repeat) { // 如果动画重复执行,则 elapsed > duration,计算 ratio 时需取模 ratio = (elapsed % duration) / duration; ratio = easeFn(ratio); } else { ratio = elapsed / duration; if (ratio < 1) { // 动画未执行完 ratio = easeFn(ratio); } else { // 动画已执行完 if (animation.onFrame) { shape.attr(animation.onFrame(1)); } else { shape.attr(animation.toAttrs); } return true; } } if (animation.onFrame) { var attrs = animation.onFrame(ratio); shape.attr(attrs); } else { _update(shape, animation, ratio); } return false; } var Timeline = /** @class */ (function () { /** * 时间轴构造函数,依赖于画布 * @param {} */ function Timeline(canvas) { /** * 执行动画的元素列表 * @type {IElement[]} */ this.animators = []; /** * 当前时间 * @type {number} */ this.current = 0; /** * 定时器 * @type {d3Timer.Timer} */ this.timer = null; this.canvas = canvas; } /** * 初始化定时器 */ Timeline.prototype.initTimer = function () { var _this = this; var isFinished = false; var shape; var animations; var animation; this.timer = d3Timer.timer(function (elapsed) { _this.current = elapsed; if (_this.animators.length > 0) { for (var i = _this.animators.length - 1; i >= 0; i--) { shape = _this.animators[i]; if (shape.destroyed) { // 如果已经被销毁,直接移出队列 _this.removeAnimator(i); continue; } if (!shape.isAnimatePaused()) { animations = shape.get('animations'); for (var j = animations.length - 1; j >= 0; j--) { animation = animations[j]; isFinished = update(shape, animation, elapsed); if (isFinished) { animations.splice(j, 1); isFinished = false; if (animation.callback) { animation.callback(); } } } } if (animations.length === 0) { _this.removeAnimator(i); } } var autoDraw = _this.canvas.get('autoDraw'); // 非自动渲染模式下,手动调用 canvas.draw() 重新渲染 if (!autoDraw) { _this.canvas.draw(); } } }); }; /** * 增加动画元素 */ Timeline.prototype.addAnimator = function (shape) { this.animators.push(shape); }; /** * 移除动画元素 */ Timeline.prototype.removeAnimator = function (index) { this.animators.splice(index, 1); }; /** * 是否有动画在执行 */ Timeline.prototype.isAnimating = function () { return !!this.animators.length; }; /** * 停止定时器 */ Timeline.prototype.stop = function () { if (this.timer) { this.timer.stop(); } }; /** * 停止时间轴上所有元素的动画,并置空动画元素列表 * @param {boolean} toEnd 是否到动画的最终状态,用来透传给动画元素的 stopAnimate 方法 */ Timeline.prototype.stopAllAnimations = function (toEnd) { if (toEnd === void 0) { toEnd = true; } this.animators.forEach(function (animator) { animator.stopAnimate(toEnd); }); this.animators = []; this.canvas.draw(); }; /** * 获取当前时间 */ Timeline.prototype.getTime = function () { return this.current; }; return Timeline; }()); exports.default = Timeline; //# sourceMappingURL=timeline.js.map