UNPKG

tinyjs-plugin-easy-animation

Version:
518 lines (500 loc) 18.6 kB
/*! * Name: tinyjs-plugin-easy-animation * Description: a easy way to use tiny tween animation * Author: zhaizheng.zz * Version: v0.1.3 */ // AppX: adapter for the alibaba mini program if (typeof $global !== 'undefined') { window = $global.window navigator = window.navigator Tiny = $global.Tiny } 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var xEval = function xEval(localValue, operation) { var FN = Function; if (typeof localValue === 'number') { return new FN('return ' + localValue + operation)(); } return { x: new FN('return ' + localValue.x + operation)(), y: new FN('return ' + localValue.y + operation)() }; }; var parsePercent = function parsePercent(percentValue) { return percentValue.slice(0, -1) / 100; }; var isUndefined = function isUndefined(value) { return value === void 0; }; var isObject = function isObject(target) { return Object.prototype.toString.call(target) === '[object Object]'; }; var deepCloneConfig = function deepCloneConfig(config) { var configClone = {}; for (var key in config) { if (config.hasOwnProperty(key)) { if (config[key] && _typeof(config[key]) === 'object') { if (Array.isArray(config[key])) { configClone[key] = config[key].map(function (item) { if ((typeof item === 'undefined' ? 'undefined' : _typeof(item)) === 'object') { return deepCloneConfig(item); } return item; }); } else { configClone[key] = deepCloneConfig(config[key]); } } else { configClone[key] = config[key]; } } } return configClone; }; var xRequestAnimationFrame = function xRequestAnimationFrame(callback) { if (navigator.canUseBinding) { return setTimeout(function () { callback && callback(); }, 0); } else { return window.requestAnimationFrame(function () { callback && callback(); }); } }; var xCancelAnimationFrame = function xCancelAnimationFrame(handler) { if (navigator.canUseBinding) { clearTimeout(handler); } else { window.cancelAnimationFrame(handler); } }; var getParentRelativePosValue = function getParentRelativePosValue(displayObject, property, targetValue, toValue, clipIndex) { displayObject.displayObjectUpdateTransform(); var operator = toValue < targetValue ? '-' : '+'; var localValue = void 0; var deltaValue = toValue - targetValue; if (property === 'position.x') { localValue = displayObject.localTransform.tx; } else if (property === 'position.y') { localValue = displayObject.localTransform.ty; } else { localValue = { x: displayObject.localTransform.tx, y: displayObject.localTransform.ty }; } toValue = '' + operator + Math.abs(deltaValue); if (clipIndex === 0) { displayObject.__easyAnimationOperation = toValue; return { targetValue: localValue, toValue: (typeof localValue === 'undefined' ? 'undefined' : _typeof(localValue)) === 'object' ? { x: toValue, y: toValue } : toValue }; } else { var _targetValue = xEval(localValue, displayObject.__easyAnimationOperation); displayObject.__easyAnimationOperation += toValue; return { targetValue: _targetValue, toValue: (typeof localValue === 'undefined' ? 'undefined' : _typeof(localValue)) === 'object' ? { x: toValue, y: toValue } : toValue }; } }; /** * @name tinyjs-plugin-easy-animation * @overview a easy way to use tiny tween animation * @author zhaizheng.zz * @license MIT */ var ANIMATION_FILL_MODE = { 'FORWARDS': 'forwards', 'BACKWARDS': 'backwards' }; var EasyAnimation = function () { function EasyAnimation(displayObject) { classCallCheck(this, EasyAnimation); this.pluginName = 'easyAnimation'; this.displayObject = displayObject; this.tweenGroup = new Tiny.TWEEN.Group(); this.tweenAnimationCache = {}; this.playingAimationCompleteTimes = {}; this.playingAnimation = ''; this.playTimes = 1; this.chainAnimationCompleteTimes = 0; this.playing = false; this.useRelativePositionValue = false; this.animationFillMode = 'forwards'; } createClass(EasyAnimation, [{ key: 'setAnimationConfig', value: function setAnimationConfig(config, useRelativePositionValue) { var _this = this; this.displayObject.updateTransform = function () { _this.tweenGroup.update(); _this.displayObject.containerUpdateTransform.call(_this.displayObject); }; this.useRelativePositionValue = useRelativePositionValue; var tweenConfigs = this.__parseAnimationConfig(deepCloneConfig(config)); this.__createTween(tweenConfigs); } }, { key: 'play', value: function play(animationName, playTimes, animationFillMode) { var animations = this.tweenAnimationCache[animationName]; if (!animations) { throw new Error('can not find animationName {' + animationName + '} in your configs.'); } if (this.playing) { return; } if (typeof playTimes === 'number') { this.playTimes = playTimes || 1; } if (typeof playTimes === 'string') { this.animationFillMode = playTimes; } if (animationFillMode) { this.animationFillMode = animationFillMode; } this.playingAnimation = animationName; this.playing = true; this.__playAnimation(animationName); } }, { key: 'stop', value: function stop() { var animations = this.tweenGroup.getAll(); animations.forEach(function (animation) { animation.stop(); }); this.playing = false; this.__setAnimationClipCompleteTimes(this.playingAnimation, 0); this.playingAnimation = ''; this.playTimes = 1; } }, { key: 'clear', value: function clear() { this.tweenAnimationCache = {}; this.tweenGroup.removeAll(); this.playingAnimation = ''; this.playingAimationCompleteTimes = {}; this.playTimes = 1; this.playing = false; } }, { key: '__playAnimation', value: function __playAnimation(animationName) { var animations = this.tweenAnimationCache[animationName]; if (!animations) return; animations.forEach(function (animation) { animation.start(); }); } }, { key: '__createTween', value: function __createTween(tweenConfigs) { var _this2 = this; var animationNames = Object.keys(tweenConfigs); animationNames.forEach(function (animationName) { var tweenConfig = tweenConfigs[animationName]; var propertyKeys = Object.keys(tweenConfig); var displayObjectInitProperty = {}; _this2.tweenAnimationCache[animationName] = propertyKeys.map(function (property) { var configs = tweenConfig[property]; var tweenCount = 0; var headTween = void 0; configs.reduce(function (prevItem, curItem) { var property = curItem.property, target = curItem.target, to = curItem.to, easeFunction = curItem.easeFunction, duration = curItem.duration, delay = curItem.delay; var _updateProperty = property.split('.'); var _easeFunction = typeof easeFunction === 'function' ? easeFunction : easeFunction.split('.').reduce(function (prev, cur) { return prev[cur]; }, Tiny.TWEEN.Easing); var tween = new Tiny.TWEEN.Tween(target, _this2.tweenGroup); var initValue = target[property] || _extends({}, target); _this2.__cacheDisplayObjectInitPropertyValue(_updateProperty, property, displayObjectInitProperty); tween.animationName = animationName; tween.to(to, duration); tween.easing(_easeFunction); tween.delay(delay); tween.onUpdate(function () { _this2.__updateDisplayObjectProperty(_updateProperty, isUndefined(target[property]) ? target : target[property]); }); tween.onComplete(function (data) { var playingAnimations = _this2.tweenAnimationCache[_this2.playingAnimation]; if (!playingAnimations) { return; } var animationTotalCount = playingAnimations.reduce(function (prev, cur) { return prev + cur.tweenCount; }, 0); var animationPlayCount = animationTotalCount * _this2.playTimes; _this2.__setAnimationClipCompleteTimes(_this2.playingAnimation); _this2.displayObject.emit('onAnimationClipEnd', data); if (_this2.useRelativePositionValue && property === 'position') { target.x = initValue.x; target.y = initValue.y; } else { target[property] = initValue; } var clipCompleteTimes = _this2.__getAnimationClipCompleteTimes(_this2.playingAnimation); if (_this2.playTimes === Infinity) { if (animationTotalCount === clipCompleteTimes) { _this2.__setAnimationClipCompleteTimes(_this2.playingAnimation, 0); var rafId = xRequestAnimationFrame(function () { _this2.__playAnimation(_this2.playingAnimation); xCancelAnimationFrame(rafId); }); } } else { if (clipCompleteTimes % animationTotalCount === 0 && _this2.playTimes > _this2.chainAnimationCompleteTimes + 1) { _this2.chainAnimationCompleteTimes++; var _rafId = xRequestAnimationFrame(function () { _this2.__playAnimation(_this2.playingAnimation); xCancelAnimationFrame(_rafId); }); } if (clipCompleteTimes === animationPlayCount) { _this2.playing = false; _this2.__setAnimationClipCompleteTimes(_this2.playingAnimation, 0); _this2.playTimes = 1; _this2.chainAnimationCompleteTimes = 0; if (_this2.animationFillMode === ANIMATION_FILL_MODE.BACKWARDS) { Object.keys(displayObjectInitProperty).forEach(function (key) { var _updateProperty = key.split('.'); _this2.__updateDisplayObjectProperty(_updateProperty, displayObjectInitProperty[key]); }); } _this2.displayObject.emit('onAnimationEnd', _this2.playingAnimation); } } }); tweenCount++; if (!prevItem) { headTween = tween; return headTween; } prevItem.chain(tween); return tween; }, null); headTween.tweenCount = tweenCount; return headTween; }); }); } }, { key: '__getAnimationClipCompleteTimes', value: function __getAnimationClipCompleteTimes(animationName) { return this.playingAimationCompleteTimes[animationName]; } }, { key: '__setAnimationClipCompleteTimes', value: function __setAnimationClipCompleteTimes(animationName, times) { if (!isUndefined(times)) { this.playingAimationCompleteTimes[animationName] = times; return; } if (this.playingAimationCompleteTimes[animationName]) { this.playingAimationCompleteTimes[animationName]++; } else { this.playingAimationCompleteTimes[animationName] = 1; } } }, { key: '__updateDisplayObjectProperty', value: function __updateDisplayObjectProperty(updatePropertyList, value) { var _updatePropertyList = slicedToArray(updatePropertyList, 2), property0 = _updatePropertyList[0], property1 = _updatePropertyList[1]; if (isUndefined(this.displayObject[property0])) { console.warn('DisplayObject no ' + property0); return; } if (property1) { this.displayObject[property0][property1] = value; return; } if (isObject(this.displayObject[property0]) && !isUndefined(this.displayObject[property0]['x']) && !isUndefined(this.displayObject[property0]['y'])) { this.displayObject[property0]['x'] = isObject(value) ? value.x : value; this.displayObject[property0]['y'] = isObject(value) ? value.y : value; } else { this.displayObject[property0] = value; } } }, { key: '__cacheDisplayObjectInitPropertyValue', value: function __cacheDisplayObjectInitPropertyValue(_updateProperty, property, map) { if (!isUndefined(map[property])) { return; } if (_updateProperty.length > 1) { map[property] = this.displayObject[_updateProperty[0]][_updateProperty[1]]; } else { var value = this.displayObject[_updateProperty[0]]; map[property] = isObject(value) ? { x: value.x, y: value.y } : value; } return map; } }, { key: '__parseAnimationConfig', value: function __parseAnimationConfig(config) { var _this3 = this; var animationNames = Object.keys(config); var tweenParams = {}; var tweenConfigs = {}; animationNames.forEach(function (animationName) { var curAnimationConfig = config[animationName]; curAnimationConfig.forEach(function (animation) { var property = animation.property, _animation$easeFuncti = animation.easeFunction, easeFunction = _animation$easeFuncti === undefined ? 'Linear.None' : _animation$easeFuncti, duration = animation.duration, clips = animation.clips; clips.map(function (item) { var percent = item.percent; if (percent) { item.percent = parsePercent(percent); } if (property === 'rotation') { item.value = Tiny.deg2radian(item.value); } return item; }).sort(function (a, b) { if (!isUndefined(a.startTime) && !isUndefined(b.startTime)) { return a.startTime - b.startTime; } return a.percent - b.percent; }).forEach(function (clip, index) { if (!clips[index + 1]) { return; } var _duration = clips[index + 1].startTime - clip.startTime; var targetValue = clip.value; var toValue = clips[index + 1].value; if (!isUndefined(clip.percent) && !isUndefined(clips[index + 1].percent)) { _duration = clips[index + 1].percent * duration - clip.percent * duration; } if (!_duration) { throw new Error('animation clips property startTime or percent is required!'); } if (_this3.useRelativePositionValue && /position/.test(property)) { var values = getParentRelativePosValue(_this3.displayObject, property, targetValue, toValue, index); targetValue = values.targetValue; toValue = values.toValue; } var target = defineProperty({}, property, targetValue); var to = defineProperty({}, property, toValue); if (property === 'position' && _this3.useRelativePositionValue) { target = _extends({}, targetValue); to = _extends({}, toValue); } var param = { property: property, target: target, to: to, duration: _duration, easeFunction: clip.easeFunction || easeFunction, delay: clip.delay || 0 }; if (tweenParams[property]) { tweenParams[property].push(param); } else { tweenParams[property] = [param]; } }); }); tweenConfigs[animationName] = tweenParams; tweenParams = {}; }); return tweenConfigs; } }]); return EasyAnimation; }(); Tiny.DisplayObject.registerPlugin('easyAnimation', EasyAnimation);