UNPKG

rc-tween-one

Version:
430 lines (399 loc) 15.6 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _styleUtils = require('style-utils'); var _easing = require('./easing'); var _easing2 = _interopRequireDefault(_easing); var _plugins = require('./plugins'); var _plugins2 = _interopRequireDefault(_plugins); var _StylePlugin = require('./plugin/StylePlugin'); var _StylePlugin2 = _interopRequireDefault(_StylePlugin); var _util = require('./util.js'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var DEFAULT_EASING = 'easeInOutQuad'; /* eslint-disable func-names */ /** * Created by jljsj on 16/1/27. */ var DEFAULT_DURATION = 450; var DEFAULT_DELAY = 0; function noop() {} _plugins2['default'].push(_StylePlugin2['default']); // 设置默认数据 function defaultData(vars, now) { var duration = vars.duration || vars.duration === 0 ? vars.duration : DEFAULT_DURATION; return { duration: vars.type === 'set' ? 0 : duration, delay: vars.delay || DEFAULT_DELAY, ease: typeof vars.ease === 'function' ? vars.ease : _easing2['default'][vars.ease || DEFAULT_EASING], onUpdate: vars.onUpdate || noop, onComplete: vars.onComplete || noop, onStart: vars.onStart || noop, onRepeat: vars.onRepeat || noop, repeat: vars.repeat || 0, repeatDelay: vars.repeatDelay || 0, yoyo: vars.yoyo || false, type: vars.type === 'from' ? 'from' : 'to', initTime: now, appearTo: typeof vars.appearTo === 'number' ? vars.appearTo : null, perTime: 0, currentRepeat: 0 }; } var Tween = function Tween(target, toData, props) { this.target = target; this.attr = props.attr || 'style'; // 时间精度补齐; this.accuracy = 0.00001; // 记录总时间; this.totalTime = 0; // 记录当前时间; this.progressTime = 0; // 记录时间轴数据; this.defaultData = []; // 每个的开始数据; this.start = {}; // 开始默认的数据; this.startDefaultData = {}; // 动画过程 this.tween = {}; // toData; this.data = toData; // 每帧的时间; this.perFrame = Math.round(1000 / 60); // 注册,第一次进入执行注册 this.register = false; // svg元素 this.isSvg = this.target.ownerSVGElement; // 设置 style var data = this.setAttrIsStyle(); // 设置默认动画数据; this.setDefaultData(data); }; var p = Tween.prototype; p.setAttrIsStyle = function () { var _this = this; var data = []; this.data.forEach(function (d, i) { var _d = (0, _extends3['default'])({}, d); if (_this.attr === 'style') { data[i] = {}; Object.keys(_d).forEach(function (key) { if (key in defaultData({}, 0)) { data[i][key] = _d[key]; delete _d[key]; } }); data[i].style = _d; _this.startDefaultData.style = _this.target.getAttribute('style'); } else if (_this.attr === 'attr') { Object.keys(_d).forEach(function (key) { if (key === 'style' && Array.isArray(d[key])) { throw new Error('Style should be the object.'); } if (key === 'bezier') { _d.style = (0, _extends3['default'])({}, _d.style, { bezier: _d[key] }); delete _d[key]; _this.startDefaultData.style = _this.target.getAttribute('style'); } else { _this.startDefaultData[key] = _this.target.getAttribute(key); } }); data[i] = _d; } }); return data; }; p.setDefaultData = function (_vars) { var _this2 = this; var now = 0; var repeatMax = false; var data = _vars.map(function (item) { var appearToBool = typeof item.appearTo === 'number'; // 加上延时,在没有播放过时; if (!appearToBool) { now += item.delay || 0; } var appearToTime = (item.appearTo || 0) + (item.delay || 0); // 获取默认数据 var tweenData = defaultData(item, appearToBool ? appearToTime : now); tweenData.vars = {}; Object.keys(item).forEach(function (_key) { if (!(_key in tweenData)) { var _data = item[_key]; if (_key in _plugins2['default']) { tweenData.vars[_key] = new _plugins2['default'][_key](_this2.target, _data, tweenData.type); } else if (_key.match(/color/i) || _key === 'stroke' || _key === 'fill') { tweenData.vars[_key] = { type: 'color', vars: (0, _styleUtils.parseColor)(_data) }; } else if (typeof _data === 'number' || _data.split(/[,|\s]/g).length <= 1) { var vars = parseFloat(_data); var unit = _data.toString().replace(/[^a-z|%]/g, ''); var count = _data.toString().replace(/[^+|=|-]/g, ''); tweenData.vars[_key] = { unit: unit, vars: vars, count: count }; } else if ((_key === 'd' || _key === 'points') && 'SVGMorph' in _plugins2['default']) { tweenData.vars[_key] = new _plugins2['default'].SVGMorph(_this2.target, _data, _key); } } }); if (tweenData.yoyo && !tweenData.repeat) { console.warn('Warning: yoyo must be used together with repeat;'); // eslint-disable-line } if (tweenData.repeat === -1) { repeatMax = true; } var repeat = tweenData.repeat === -1 ? 0 : tweenData.repeat; if (appearToBool) { // 如果有 appearTo 且这条时间比 now 大时,,总时间用这条; var appearNow = item.appearTo + (item.delay || 0) + tweenData.duration * (repeat + 1) + tweenData.repeatDelay * repeat; now = appearNow >= now ? appearNow : now; } else if (tweenData.delay < -tweenData.duration) { // 如果延时小于 负时间时,,不加,再减回延时; now -= tweenData.delay; } else { // repeat 为 -1 只记录一次。不能跟 reverse 同时使用; now += tweenData.duration * (repeat + 1) + tweenData.repeatDelay * repeat; } tweenData.mode = ''; return tweenData; }); this.totalTime = repeatMax ? Number.MAX_VALUE : now; this.defaultData = data; }; p.getComputedStyle = function () { var style = typeof window !== 'undefined' && document.defaultView ? document.defaultView.getComputedStyle(this.target) : {}; // 如果是 SVG, 样式全部提出为 transformSVG, 兼容 safari 不能获取 transform; if (this.isSvg) { var transform = style[(0, _styleUtils.checkStyleName)('transform')] || 'none'; if (transform === 'none') { var attrStyle = this.target.getAttribute('style'); if (attrStyle && attrStyle.indexOf('transform:') >= 0) { transform = attrStyle.split(';').filter(function (k) { return k.indexOf('transform:') >= 0; }).map(function (item) { return (0, _styleUtils.createMatrix)(item.split(':')[1].trim()).toString(); })[0]; } else if (this.target.getAttribute('transform')) { // 暂时不支持标签上的 transform,后期增加; console.warn('Do not add transform on the label, otherwise it will be invalid.'); // eslint-disable-line no-console } } style.transformSVG = transform; } return style; }; p.getAnimStartData = function (item) { var _this3 = this; var start = {}; Object.keys(item).forEach(function (_key) { if (_key in _plugins2['default'] || _this3.attr === 'attr' && (_key === 'd' || _key === 'points')) { _this3.computedStyle = _this3.computedStyle || _this3.getComputedStyle(); start[_key] = item[_key].getAnimStart(_this3.computedStyle, _this3.tween, _this3.isSvg); return; } if (_this3.attr === 'attr') { // 除了d和这points外的标签动画; var attribute = _this3.target.getAttribute(_key); var data = attribute === 'null' || !attribute ? 0 : attribute; if (_key.match(/color/i) || _key === 'stroke' || _key === 'fill') { data = !data && _key === 'stroke' ? 'rgba(255, 255, 255, 0)' : data; data = (0, _styleUtils.parseColor)(data); start[_key] = data; } else if (parseFloat(data) || parseFloat(data) === 0 || data === 0) { var unit = data.toString().replace(/[^a-z|%]/g, ''); start[_key] = unit !== item[_key].unit ? (0, _util.startConvertToEndUnit)(_this3.target, _key, parseFloat(data), unit, item[_key].unit) : parseFloat(data); } return; } start[_key] = _this3.target[_key] || 0; }); return start; }; p.setAnimData = function (data) { var _this4 = this; Object.keys(data).forEach(function (key) { if (key in _plugins2['default'] || _this4.attr === 'attr' && (key === 'd' || key === 'points')) { return; } _this4.target[key] = data[key]; }); }; p.setRatio = function (ratio, endData, i) { var _this5 = this; Object.keys(endData.vars).forEach(function (_key) { if (_key in _plugins2['default'] || _this5.attr === 'attr' && (_key === 'd' || _key === 'points')) { endData.vars[_key].setRatio(ratio, _this5.tween, _this5.isSvg && _this5.computedStyle); return; } var endVars = endData.vars[_key]; var startVars = _this5.start[i][_key]; var data = void 0; if (_this5.attr === 'attr') { // 除了d和这points外的标签动画; if (!endVars.type) { data = endVars.unit.charAt(1) === '=' ? startVars + endVars.vars * ratio + endVars.unit : (endVars.vars - startVars) * ratio + startVars + endVars.unit; _this5.target.setAttribute(_key, data); } else if (endVars.type === 'color') { if (endVars.vars.length === 3 && startVars.length === 4) { endVars.vars[3] = 1; } data = endVars.vars.map(function (_endData, _i) { var startData = startVars[_i] || 0; return (_endData - startData) * ratio + startData; }); _this5.target.setAttribute(_key, (0, _styleUtils.getColor)(data)); } } }); this.setAnimData(this.tween); }; p.render = function () { var _this6 = this; var reverse = this.reverse; this.defaultData.forEach(function (item, i) { var initTime = item.initTime; var duration = (0, _styleUtils.toFixed)(item.duration); // 处理 yoyo 和 repeat; yoyo 是在时间轴上的, 并不是倒放 var repeatNum = Math.ceil((_this6.progressTime - initTime) / (duration + item.repeatDelay)) - 1 || 0; repeatNum = repeatNum < 0 ? 0 : repeatNum; if (item.repeat) { if (item.repeat < repeatNum && item.repeat !== -1) { return; } if (item.repeat || item.repeat <= repeatNum) { initTime += repeatNum * (duration + item.repeatDelay); } } var startData = item.yoyo && repeatNum % 2 ? 1 : 0; var endData = item.yoyo && repeatNum % 2 ? 0 : 1; startData = item.type === 'from' ? 1 - startData : startData; endData = item.type === 'from' ? 1 - endData : endData; // 精度损失,只取小数点后10位。 var progressTime = (0, _styleUtils.toFixed)(_this6.progressTime - initTime); var ratio = void 0; // 开始注册; // from 时需先执行参数位置; var fromDelay = item.type === 'from' ? item.delay : 0; if (progressTime + fromDelay >= 0) { if (!_this6.start[i]) { // 设置 start _this6.start[i] = _this6.getAnimStartData(item.vars); if (progressTime < _this6.perFrame) { ratio = !item.duration && !item.delay ? item.ease(1, startData, endData, 1) : item.ease(0, startData, endData, 1); _this6.setRatio(ratio, item, i); } else if (progressTime > duration) { ratio = item.ease(1, startData, endData, 1); _this6.setRatio(ratio, item, i); } if (!_this6.register || i && !initTime) { _this6.register = true; if (progressTime === 0 && item.duration) { return; } } } } var e = { index: i, target: _this6.target }; var cb = (0, _extends3['default'])({ moment: _this6.progressTime }, e); if (progressTime >= (item.delay && reverse ? -_this6.perFrame + _this6.accuracy : 0) && !(progressTime > duration && item.mode === 'onComplete') && _this6.start[i]) { var updateAnim = _this6.updateAnim === 'update'; progressTime = progressTime < _this6.perFrame - _this6.accuracy && !reverse ? 0 : progressTime; if ((progressTime >= duration - _this6.accuracy && !reverse || reverse && progressTime <= 0) && repeatNum >= item.repeat) { // onReveresComplete 和 onComplete 统一用 onComplete; ratio = item.ease(reverse ? 0 : 1, startData, endData, 1); _this6.setRatio(ratio, item, i, item.currentRepeat !== repeatNum); if (!item.reset && !updateAnim) { // duration 为 0 时的一个回调; if (!duration) { item.onStart(e); cb.mode = 'onStart'; _this6.onChange(cb); item.onUpdate((0, _extends3['default'])({ ratio: ratio }, e)); cb.mode = 'onUpdate'; _this6.onChange(cb); } item.onComplete(e); } else if (progressTime >= duration + _this6.perFrame - _this6.accuracy) { return; } item.mode = 'onComplete'; } else if (duration) { var currentProgress = progressTime < 0 ? 0 : progressTime; currentProgress = currentProgress > duration ? duration : currentProgress; ratio = item.ease(currentProgress, startData, endData, duration); _this6.setRatio(ratio, item, i); if (!updateAnim) { if (item.repeat && repeatNum > 0 && item.currentRepeat !== repeatNum) { item.mode = 'onRepeat'; item.currentRepeat = repeatNum; item.onRepeat((0, _extends3['default'])({}, e, { repeatNum: repeatNum })); } else if ((typeof item.perTime !== 'number' || progressTime === 0 || reverse && item.perTime >= _this6.reverseStartTime - initTime) && item.mode !== 'onStart') { // onReveresStart 和 onStart 统一用 onStart; item.mode = 'onStart'; item.onStart(e); } else { item.mode = 'onUpdate'; item.onUpdate((0, _extends3['default'])({ ratio: ratio }, e)); } } } if (!updateAnim) { cb.mode = item.mode; _this6.onChange(cb); } item.perTime = progressTime; if (item.reset) { delete item.reset; } } }); }; // 播放帧 p.frame = function (moment) { var _this7 = this; this.progressTime = moment; this.defaultData.forEach(function (item) { var t = _this7.progressTime - item.duration - item.initTime; if (t < _this7.perFrame && t > 0) { _this7.progressTime = item.duration + item.initTime; } }); this.render(); }; p.resetAnimData = function () { this.tween = {}; this.start = {}; }; p.resetDefaultStyle = function () { var _this8 = this; this.tween = {}; this.defaultData = this.defaultData.map(function (item) { item.reset = true; delete item.mode; return item; }); Object.keys(this.startDefaultData).forEach(function (key) { if (!(key in defaultData({}, 0))) { _this8.target.setAttribute(key, _this8.startDefaultData[key]); } }); }; p.reStart = function (style) { var _this9 = this; this.start = {}; this.target.style.cssText = ''; Object.keys(style || {}).forEach(function (key) { _this9.target.style[key] = (0, _styleUtils.stylesToCss)(key, style[key]); }); this.setAttrIsStyle(); this.resetDefaultStyle(); }; p.onChange = noop; exports['default'] = Tween; module.exports = exports['default'];