var dataUtil = require("../utils/data_structure_util"); var classUtil = require("../utils/class_util"); var Track = require("./Track"); var Eventful = require("../event/Eventful"); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } /** * @class qrenderer.animation.AnimationProcess * AnimationProcess represents for an entire animation process, each instance of the Element class has a list to store all the animation processes. * Each process in the list will be executed in order. Only one process can be in running state at a certain point. All the animation processes will be scheduled by the GlobalAnimationMgr class. * An event called 'done' will be trigged when the animation process finished. Current process will be deleted after the 'done' event is triggered. * If more than one process exists in the list, and one of them is set to run in loop mode, then any process behind it will not be executed. * * * AnimationProcess 表示一次完整的动画过程,每一个元素(Element)中都有一个列表,用来存储本实例上的所有动画过程。 * 列表中的动画过程按照顺序获得运行机会,在特定的时间点上只有一个 AnimationProcess 处于运行状态,系统中的所有动画过程都由 GlobalAnimationMgr 类进行调度。 * AnimationProcess 运行完成之后会触发一个 done 事件,Element 实例在收到 done 事件之后,会把当前的动画过程从列表中删除。 * 如果 Element 实例的动画过程列表中存在多个实例,其中某个过程是无限循环运行的,那么后续所有动画过程都不会获得到运行机会。 * * @author 大漠穷秋 <damoqiongqiu@126.com> * @docauthor 大漠穷秋 <damoqiongqiu@126.com> */ var AnimationProcess = /*#__PURE__*/ function () { /** * @method constructor AnimationProcess * @param {Object} element * The element needes animating functions. * * * 需要动画功能的元素。 */ function AnimationProcess(element) { _classCallCheck(this, AnimationProcess); this.element = element; this._trackCacheMap = new Map(); this._delay = 0; this._running = false; this._paused = false; classUtil.inheritProperties(this, Eventful, this.options); } /** * @method when * Create a track for each property that needs to be animated. The animation properties supported by Quark Renderer are position, shape, and style. * * * 为每一种需要进行动画的属性创建一条轨道,Quark Renderer 能支持动画的属性有 position、shape、style。 * @param {Number} time * Lifetime of the keyframe, in milliseconds. * * * 关键帧的存活时间,单位是毫秒ms。 * @param {Object} config * Properties of the keyframe, in key-value shape. * * * 关键帧的属性值,key-value 表示。 * @return {qrenderer.animation.AnimationProcess} */ _createClass(AnimationProcess, [{ key: "when", value: function when(time, config) { var _this = this; var flattenMap = new Map(); dataUtil.flattenObj(config, flattenMap); flattenMap.forEach(function (value, key, map) { var track = _this._trackCacheMap.get(key); if (!track) { track = new Track({ element: _this.element, path: key, delay: _this._delay }); //If there is no frame 0 in the config object, add an 0 frame automatically, use current properties of the element as the value of the 0 frame. //如果参数中没有提供第 0 帧,自动补第 0 帧,以元素上当前的属性值为关键帧的值。 if (time !== 0) { var temp = dataUtil.getAttrByPath(_this.element, key); if (temp == null || temp == undefined) { temp = 0; } track.addKeyFrame({ time: 0, value: dataUtil.clone(temp) }); } _this._trackCacheMap.set(key, track); } track.addKeyFrame({ time: time, value: dataUtil.clone(value) }); }); return this; } /** * @method start * Start to execute the animation. * * 开始执行动画。 * @param {Boolean} loop * Whether loop the animation. * * * 是否循环。 * @param {String|Function} [easing] * Name of the easing function, see {@link qrenderer.animation.easing easing engine}. * * * 缓动函数名称,详见{@link qrenderer.animation.easing 缓动引擎}。 * @param {Boolean} forceAnimate * Whethe to force the animation. * * * 是否强制开启动画。 * @return {qrenderer.animation.AnimationProcess} */ }, { key: "start", value: function start() { var loop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var easing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var forceAnimate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; this._running = true; this._paused = false; this.trigger("start"); if (!this._trackCacheMap.size) { this.trigger("done"); return this; } this._trackCacheMap.forEach(function (track, key, map) { track && track.start(loop, easing, forceAnimate); }); return this; } /** * @method nextFrame * Enter next frame. * * * 进入下一帧。 * @param {Number} time * Current time. * * * 当前时间。 * @param {Number} delta * Time offset. * * * 时间偏移量。 */ }, { key: "nextFrame", value: function nextFrame(time, delta) { var _this2 = this; this._running = true; this._paused = false; var deferredEvents = []; var deferredTracks = []; var percent = ""; var isFinished = true; this._trackCacheMap.forEach(function (track, key, map) { var result = track.nextFrame(time, delta); if (dataUtil.isString(result)) { deferredEvents.push(result); deferredTracks.push(track); } else if (dataUtil.isNumeric(result)) { percent = result; } isFinished = isFinished && track.isFinished; if (dataUtil.isNumeric(percent)) { _this2.trigger("during", _this2.element, track._path, track._currentValue, percent); } }); var len = deferredEvents.length; for (var i = 0; i < len; i++) { deferredTracks[i].fire(deferredEvents[i]); } if (isFinished) { this.trigger("done"); } } /** * @method stop * Stop the animation. * * * 停止动画。 * @param {Boolean} forwardToLast * Whether move to the last frame before animation stops. * * * 是否在动画停止之前跳到最后一帧。 */ }, { key: "stop", value: function stop(forwardToLast) { var _this3 = this; this._running = false; this._paused = false; this._trackCacheMap.forEach(function (track, key, map) { track.stop(_this3.element, 1); }); this._trackCacheMap = new Map(); this.trigger("stop"); return this; } /** * @method pause * Pause the animation. * * * 暂停动画。 */ }, { key: "pause", value: function pause() { this._running = false; this._paused = true; this._trackCacheMap.forEach(function (track, key, map) { track.pause(); }); this.trigger("pause"); return this; } /** * @method resume * Resume the animation. * * * 恢复动画。 */ }, { key: "resume", value: function resume() { this._running = true; this._paused = false; this._trackCacheMap.forEach(function (track, key, map) { track.resume(); }); this.trigger("resume"); return this; } /** * @method during * Callback for each animation frame, this is to facilitate chained calls. * * * 每一帧的回调函数,方便链式调用。 * @param {Function} callback * @return {qrenderer.animation.AnimationProcess} */ }, { key: "during", value: function during(callback) { this.on("during", callback); return this; } /** * @method done * Callback function for the end of animation, this is to facilitate chained calls. * * * 添加动画结束的回调,方便链式调用。 * @param {Function} callback * @return {qrenderer.animation.AnimationProcess} */ }, { key: "done", value: function done(callback) { this.on("done", callback); return this; } /** * @method isFinished * Determine wether the entire animation process has finished, when the animations of all the tracks are finished, the animation process is finished. * * * 判断整个动画过程是否已经完成,所有 Track 上的动画都完成则整个动画过程完成。 */ }, { key: "isFinished", value: function isFinished() { var isFinished = true; this._trackCacheMap.forEach(function (track, key, map) { if (!track.isFinished) { isFinished = false; } }); return isFinished; } /** * @method isPaused * Wether the process is paused. * * * 是否暂停。 */ }, { key: "isPaused", value: function isPaused() { return !!this._paused; } /** * @method delay * Set the delay time of current process. * * * 设置动画延迟开始的时间。 * @param {Number} time * In milliseconds. * * * 单位ms。 * @return {qrenderer.animation.AnimationProcess} */ }, { key: "delay", value: function delay(time) { this._delay = time; return this; } }]); return AnimationProcess; }(); classUtil.mixin(AnimationProcess, Eventful); var _default = AnimationProcess; module.exports = _default;