From 1c7a1383ec45ed88f785c7ee833d83ec353b0bf7 Mon Sep 17 00:00:00 2001 From: dalisoft Date: Thu, 7 Sep 2017 11:14:13 +0500 Subject: [PATCH] * v3.6.0 * introduce the fast lite version --- README.md | 20 +++ examples/test.html | 13 +- lite.js | 42 +++++ logo/box.svg | 14 ++ logo/es6-logo.svg | 9 + package.json | 9 +- rollup.config.lite.js | 42 +++++ src/Tween.Lite.js | 4 + src/dist/NodeCache.js | 6 +- src/dist/Timeline.js | 97 ++++++----- src/dist/Tween.Lite.js | 374 +++++++++++++++++++++++++++++++++++++++++ src/dist/Tween.js | 83 ++++++--- src/dist/core.js | 6 +- src/shim.js | 34 ++-- test.js | 16 +- 15 files changed, 668 insertions(+), 101 deletions(-) create mode 100644 lite.js create mode 100644 logo/box.svg create mode 100644 logo/es6-logo.svg create mode 100644 rollup.config.lite.js create mode 100644 src/Tween.Lite.js create mode 100644 src/dist/Tween.Lite.js diff --git a/README.md b/README.md index 7c9d975..cbb369b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,26 @@ ES6 implementation of tween.js +# News (`Lite` version is released)! + +You can use the `Lite` version of ES6 which lighter (~8Kb minified), faster (~10% faster executioin), simpler (like the original one), memory effecient and better (can tween second-level Objects/Array). Optimized for runtime performance, no-lag anymore. +When you want building mobile apps that loading files from server, use `Lite` for better performance. +Differences when using `Lite`: +* 2-times lighter size +* No `Timeline` instance +* No `String` tween support +* No `Deep tween` support (does 2-level) +* Uses original `Interpolation` instances for `Bezier` interpolation +* Faster performance and execution speed +* Memory effecient +* No more shims required +* No `Plugins` support +* No `DOM Get/Set`, `Renderer` instance/plugin/add-on support +* No full-Event system, just 3 event support (`onStart`, `onUpdate`, `onComplete`) +* No `seek`, `reverse` support +* No event fire when `stop`, `pause`, `etc` +* No `*`, `/`, `%` relatives support + [![size](http://img.badgesize.io/https://unpkg.com/es6-tween?cache=false)](http://unpkg.com/es6-tween) [![gzipsize](http://img.badgesize.io/https://unpkg.com/es6-tween?compression=gzip&cache=false)](http://unpkg.com/es6-tween) [![CDNJS](https://img.shields.io/cdnjs/v/es6-tween.svg)](https://cdnjs.com/libraries/es6-tween) diff --git a/examples/test.html b/examples/test.html index cf62fcd..30e4257 100644 --- a/examples/test.html +++ b/examples/test.html @@ -15,7 +15,7 @@ .line { width: 200px; - height: 1px; + height: 2px; position: absolute; } @@ -27,6 +27,7 @@ + diff --git a/lite.js b/lite.js new file mode 100644 index 0000000..6f3e1b6 --- /dev/null +++ b/lite.js @@ -0,0 +1,42 @@ +import buble from 'rollup-plugin-buble' +import uglify from 'rollup-plugin-uglify' +import { minify } from 'uglify-es' + +const { min } = process.env +const isMinify = min === 'true' +const minSuffix = isMinify ? '.min' : '' + +const plugins = [ + // ES6->ES5 syntax/code transpiler + buble({ + // Spread to Object merge/assign + objectAssign: `Object.assign`, + // Features + transforms: { + // For of feature + dangerousForOf: true + } + }) +] + +if ( isMinify ) { + plugins.push( + // Minify + uglify({ + sourceMap: { + filename: `src/Tween.js`, + url: `lite/Tween${minSuffix}.js.map` + } + }, minify) + ); +} + +export default { + entry: 'src/Tween.Lite.js', + format: 'umd', + sourceMap: true, + context: 'this', + dest: `lite/Tween${minSuffix}.js`, + moduleName: 'TWEEN', + plugins: plugins +} diff --git a/logo/box.svg b/logo/box.svg new file mode 100644 index 0000000..3e7db9f --- /dev/null +++ b/logo/box.svg @@ -0,0 +1,14 @@ + + +RealDRAW + + + + + + + + + + + diff --git a/logo/es6-logo.svg b/logo/es6-logo.svg new file mode 100644 index 0000000..eb9e97f --- /dev/null +++ b/logo/es6-logo.svg @@ -0,0 +1,9 @@ + + +RealDRAW + + + + + + diff --git a/package.json b/package.json index b819d96..15e7af1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "es6-tween", - "version": "3.5.9", + "version": "3.6.0", "description": "ES6 implementation of amazing tween.js", "browser": "dist/Tween.min.js", "cdn": "dist/Tween.min.js", @@ -13,12 +13,17 @@ "source": "rollup -c --environment min:false", "minify": "rollup -c --environment min:true", "build": "npm run source && npm run minify", + "source-lite": "rollup -c lite.js --environment min:false", + "minify-lite": "rollup -c lite.js --environment min:true", + "build-lite": "npm run source-lite && npm run minify-lite", + "prepare": "npm run build && npm run build-lite", "dev": "rollup -c -w", + "dev-lite": "rollup -c lite.js -w", "lint": "eslint src", "fix": "eslint --fix src", "test-unit": "nodeunit test/unit/nodeunitheadless.js", "test": "npm run lint && ava --verbose", - "prepublishOnly": "npm run lint && npm run build && ava --verbose" + "prepublishOnly": "npm run lint && npm run prepare && ava --verbose" }, "repository": { "type": "git", diff --git a/rollup.config.lite.js b/rollup.config.lite.js new file mode 100644 index 0000000..01e43e2 --- /dev/null +++ b/rollup.config.lite.js @@ -0,0 +1,42 @@ +import buble from 'rollup-plugin-buble' +import uglify from 'rollup-plugin-uglify' +import { minify } from 'uglify-es' + +const { min } = process.env +const isMinify = min === 'true' +const minSuffix = isMinify ? '.min' : '' + +const plugins = [ + // ES6->ES5 syntax/code transpiler + buble({ + // Spread to Object merge/assign + objectAssign: `Object.assign`, + // Features + transforms: { + // For of feature + dangerousForOf: true + } + }) +] + +if ( isMinify ) { + plugins.push( + // Minify + uglify({ + sourceMap: { + filename: `src/Tween.Lite.js`, + url: `dist/Tween.Lite${minSuffix}.js.map` + } + }, minify) + ); +} + +export default { + entry: 'src/Tween.Lite.js', + format: 'umd', + sourceMap: true, + context: 'this', + dest: `dist/Tween.Lite${minSuffix}.js`, + moduleName: 'TWEEN', + plugins: plugins +} diff --git a/src/Tween.Lite.js b/src/Tween.Lite.js new file mode 100644 index 0000000..7b2c743 --- /dev/null +++ b/src/Tween.Lite.js @@ -0,0 +1,4 @@ +import { has, get, getAll, removeAll, remove, add, now, update, autoPlay, Plugins, isRunning } from './dist/core' +import Easing from './dist/Easing' +import Tween from './dist/Tween.Lite' +export { Plugins, has, get, getAll, removeAll, remove, add, now, update, autoPlay, isRunning, Tween, Easing } diff --git a/src/dist/NodeCache.js b/src/dist/NodeCache.js index 7330e1e..6e6efe7 100644 --- a/src/dist/NodeCache.js +++ b/src/dist/NodeCache.js @@ -1,13 +1,15 @@ +import { assign } from '../shim' + let Store = {} export default function (node, tween) { - if (!node || !node.nodeType) return tween + if (!node || !node.nodeType || !tween) return tween var ID = node.queueID || 'queue_' + Math.round(Math.random() * 1000 + Date.now()) if (!node.queueID) { node.queueID = ID } if (Store[ID]) { if (tween) { - Store[ID] = Object.assign(Store[ID], tween) + Store[ID] = assign(Store[ID], tween) } return Store[ID] } diff --git a/src/dist/Timeline.js b/src/dist/Timeline.js index 9a3163e..15d9883 100644 --- a/src/dist/Timeline.js +++ b/src/dist/Timeline.js @@ -1,5 +1,5 @@ import Tween, { EVENT_UPDATE, EVENT_RS, EVENT_REPEAT, EVENT_REVERSE, EVENT_COMPLETE } from './Tween' -import { add, now } from './core' +import { add, now, remove } from './core' import PlaybackPosition from './PlaybackPosition' let _id = 0 @@ -8,7 +8,7 @@ class Timeline extends Tween { super() this._totalDuration = 0 this._startTime = now() - this._tweens = {} + this._tweens = [] this._elapsed = 0 this._id = _id++ this._defaultParams = params @@ -19,15 +19,37 @@ class Timeline extends Tween { return this } + fromTo (nodes, from, to, params) { + if (Array.isArray(nodes)) { + if (this._defaultParams) { + params = Object.assign(this._defaultParams, params) + } + const position = params.label + const offset = typeof position === 'number' ? position : this.position.parseLabel(typeof position !== 'undefined' ? position : 'afterLast', null) + nodes.map((node, i) => { + this.add(Tween.fromTo(node, typeof from === 'function' ? from(i, nodes.length) : from, typeof to === 'function' ? to(i, nodes.length) : to, typeof params === 'function' ? params(i, nodes.length) : params), offset + (params.stagger || 0) * i) + }) + } + return this.start() + } + + from (nodes, from, params) { + return this.fromTo(nodes, from, null, params) + } + + to (nodes, to, params) { + return this.fromTo(nodes, null, to, params) + } + addLabel (name, offset) { this.position.addLabel(name, offset) return this } map (fn) { - for (let tween in this._tweens) { - let _tween = this._tweens[tween] - fn(_tween, +tween) + for (let i = 0, len = this._tweens.length; i < len; i++) { + let _tween = this._tweens[i] + fn(_tween, i) this._totalDuration = Math.max(this._totalDuration, _tween._duration + _tween._startTime) } return this @@ -50,15 +72,18 @@ class Timeline extends Tween { if (_defaultParams) { for (let method in _defaultParams) { - tween[method](_defaultParams[method]) + if (typeof tween[method] === 'function') { + tween[method](_defaultParams[method]) + } } } const offset = typeof position === 'number' ? position : this.position.parseLabel(typeof position !== 'undefined' ? position : 'afterLast', null) - tween._startTime = this._startTime + tween._startTime = Math.max(this._startTime, tween._delayTime) tween._startTime += offset + tween._isPlaying = true this._totalDuration = Math.max(_totalDuration, tween._startTime + tween._delayTime + tween._duration) - this._tweens[tween.id] = tween + this._tweens.push(tween) this.position.setLabel('afterLast', this._totalDuration) return this } @@ -79,11 +104,6 @@ class Timeline extends Tween { return this.map(tween => tween.interpolation(interpolation)) } - reverse () { - this._reversed = !this._reversed - return this.emit(EVENT_REVERSE) - } - update (time) { let { _tweens, @@ -94,29 +114,31 @@ class Timeline extends Tween { _reversed, _yoyo, _repeat, - _isFinite + _isFinite, + _elapsed, + _isPlaying } = this - if (time < _startTime) { + if (!_isPlaying || time < _startTime) { return true } - let elapsed = Math.min(1, Math.max(0, (time - _startTime) / _totalDuration)) + let elapsed = (time - _startTime) / _totalDuration + elapsed = elapsed > 1 ? 1 : elapsed elapsed = _reversed ? 1 - elapsed : elapsed + elapsed = ((elapsed * 1000) | 0) / 1000 + if (elapsed === _elapsed) { + return true + } this._elapsed = elapsed let timing = time - _startTime let _timing = _reversed ? _totalDuration - timing : timing - for (let tween in _tweens) { - let _tween = _tweens[tween] - if (_tween.skip) { - _tween.skip = false - } else if (_tween.update(_timing)) { - continue - } else { - _tween.skip = true - } + let i = 0 + while (i < _tweens.length) { + _tweens[i].update(_timing) + i++ } this.emit(EVENT_UPDATE, elapsed, timing) @@ -130,23 +152,20 @@ class Timeline extends Tween { this.emit(_reversed ? EVENT_REVERSE : EVENT_REPEAT) if (_yoyo) { - this.reverse() + this._reversed = !_reversed } if (!_reversed && _repeatDelayTime) { - this._startTime += _totalDuration + _repeatDelayTime + this._startTime = time + _repeatDelayTime } else if (_reversed && _reverseDelayTime) { - this._startTime += _totalDuration + _reverseDelayTime + this._startTime = time + _reverseDelayTime } else { - this._startTime += _totalDuration + this._startTime = time } - for (let tween in _tweens) { - let _tween = _tweens[tween] - if (_tween.skip) { - _tween.skip = false - } - _tween.reassignValues() + while (i < _tweens.length) { + _tweens[i].reassignValues() + i++ } return true @@ -154,12 +173,8 @@ class Timeline extends Tween { this.emit(EVENT_COMPLETE) this._repeat = this._r - for (let tween in _tweens) { - let _tween = _tweens[tween] - if (_tween.skip) { - _tween.skip = false - } - } + remove(this) + this._isPlaying = false return false } diff --git a/src/dist/Tween.Lite.js b/src/dist/Tween.Lite.js new file mode 100644 index 0000000..45953eb --- /dev/null +++ b/src/dist/Tween.Lite.js @@ -0,0 +1,374 @@ +import { + add, + remove, + now +} + from './core' +import Easing from './Easing' +import Interpolation from './Interpolation' + +let _id = 0 // Unique ID + +class Tween { + constructor (object) { + this.id = _id++ + this.object = object + this._valuesStart = {} + this._valuesEnd = null + this._valuesStartRepeat = {} + + this._duration = 1000 + this._easingFunction = Easing.Linear.None + this._interpolationFunction = Interpolation.Linear + + this._startTime = 0 + this._delayTime = 0 + this._repeat = 0 + this._r = 0 + this._isPlaying = false + this._yoyo = false + this._reversed = false + + this._onStartCallbackFired = false + this._pausedTime = null + this._isFinite = true + + /* Callbacks */ + this._onStartCallback = null + this._onUpdateCallback = null + this._onCompleteCallback = null + + return this + } + + onStart (callback) { + this._onStartCallback = callback + + return this + } + + onUpdate (callback) { + this._onUpdateCallback = callback + + return this + } + + onComplete (callback) { + this._onCompleteCallback = callback + + return this + } + + isPlaying () { + return this._isPlaying + } + + isStarted () { + return this._onStartCallbackFired + } + + pause () { + if (!this._isPlaying) { + return this + } + + this._isPlaying = false + + remove(this) + this._pausedTime = now() + + return this + } + + play () { + if (this._isPlaying) { + return this + } + + this._isPlaying = true + + this._startTime += now() - this._pausedTime + add(this) + this._pausedTime = now() + + return this + } + + duration (amount) { + this._duration = typeof (amount) === 'function' ? amount(this._duration) : amount + + return this + } + + to (properties, duration = 1000) { + this._valuesEnd = properties + + this._duration = duration + + return this + } + + start (time) { + this._startTime = time !== undefined ? time : now() + this._startTime += this._delayTime + + let { + _valuesEnd, + _valuesStartRepeat, + _valuesStart, + _interpolationFunction, + object + } = this + + for (let property in _valuesEnd) { + let start = object[property] + let end = _valuesEnd[property] + + if (!object || object[property] === undefined) { + continue + } + + let obj = object[property] + + if (typeof start === 'number') { + if (typeof end === 'string') { + _valuesStartRepeat[property] = end + end = start + parseFloat(end) + } else if (Array.isArray(end)) { + end.unshift(start) + let _endArr = end + end = t => { + return _interpolationFunction(_endArr, t) + } + } + } else if (typeof end === 'object') { + if (Array.isArray(end)) { + let _endArr = end + let _start = start.map(item => item) + let i + const len = end.length + end = t => { + i = 0 + for (; i < len; i++) { + obj[i] = typeof _start[i] === 'number' ? _start[i] + (_endArr[i] - _start[i]) * t : _endArr[i] + } + return obj + } + } else { + let _endObj = end + let _start = {} + for (let p in start) { + _start[p] = start[p] + } + end = t => { + for (let i in end) { + obj[i] = typeof _start[i] === 'number' ? _start[i] + (_endObj[i] - _start[i]) * t : _endObj[i] + } + return obj + } + } + } + + _valuesStart[property] = start + _valuesEnd[property] = end + } + + add(this) + + this._isPlaying = true + + return this + } + + stop () { + let { + _isPlaying, + _startTime, + _duration + } = this + + if (!_isPlaying) { + return this + } + + this.update(_startTime + _duration) + + remove(this) + this._isPlaying = false + + return this + } + + delay (amount) { + this._delayTime = typeof (amount) === 'function' ? amount(this._delayTime) : amount + + return this + } + + repeat (amount) { + this._repeat = typeof (amount) === 'function' ? amount(this._repeat) : amount + this._r = this._repeat + this._isFinite = isFinite(amount) + + return this + } + + repeatDelay (amount) { + this._repeatDelayTime = typeof (amount) === 'function' ? amount(this._repeatDelayTime) : amount + + return this + } + + reverseDelay (amount) { + this._reverseDelayTime = typeof (amount) === 'function' ? amount(this._reverseDelayTime) : amount + + return this + } + + yoyo (state) { + this._yoyo = typeof (state) === 'function' ? state(this._yoyo) : state + + return this + } + + easing (fn) { + if (typeof fn === 'function') { + this._easingFunction = fn + } + + return this + } + + interpolation (fn) { + if (typeof fn === 'function') { + this._interpolationFunction = fn + } + + return this + } + + reassignValues () { + const { + _valuesStart, + _valuesEnd, + object + } = this + + for (let property in _valuesEnd) { + let start = _valuesStart[property] + + object[property] = start + } + + return this + } + + update (time, preserve) { + let { + _onStartCallbackFired, + _easingFunction, + _repeat, + _repeatDelayTime, + _reverseDelayTime, + _yoyo, + _reversed, + _startTime, + _duration, + _valuesStart, + _valuesEnd, + _valuesStartRepeat, + object, + _isFinite, + _isPlaying, + _onStartCallback, + _onUpdateCallback, + _onCompleteCallback + } = this + + let elapsed + let value + let property + + time = time !== undefined ? time : now() + + if (!_isPlaying || time < _startTime) { + return true + } + + if (!_onStartCallbackFired) { + if (_onStartCallback) { + _onStartCallback(object) + } + + this._onStartCallbackFired = true + } + + elapsed = (time - _startTime) / _duration + elapsed = elapsed > 1 ? 1 : elapsed + elapsed = _reversed ? 1 - elapsed : elapsed + + value = _easingFunction(elapsed) + + for (property in _valuesEnd) { + let start = _valuesStart[property] + let end = _valuesEnd[property] + + if (start === undefined) { + continue + } else if (typeof end === 'function') { + object[property] = end(value) + } else if (typeof end === 'number') { + object[property] = start + (end - start) * value + } + } + + if (_onUpdateCallback) { + _onUpdateCallback(object, elapsed) + } + + if (elapsed === 1 || (_reversed && elapsed === 0)) { + if (_repeat) { + if (_isFinite) { + this._repeat-- + } + + if (!_reversed) { + for (property in _valuesStartRepeat) { + _valuesStart[property] = _valuesEnd[property] + _valuesEnd[property] += parseFloat(_valuesStartRepeat[property]) + } + } + + if (_yoyo) { + this._reversed = !_reversed + } + + if (!_reversed && _repeatDelayTime) { + this._startTime = time + _repeatDelayTime + } else if (_reversed && _reverseDelayTime) { + this._startTime = time + _reverseDelayTime + } else { + this._startTime = time + } + + return true + } else { + if (!preserve) { + remove(this) + } + this._isPlaying = false + if (_onCompleteCallback) { + _onCompleteCallback() + } + this._repeat = this._r + _id-- + + return false + } + } + + return true + } +} + +export default Tween diff --git a/src/dist/Tween.js b/src/dist/Tween.js index 4852253..cf56d77 100644 --- a/src/dist/Tween.js +++ b/src/dist/Tween.js @@ -9,6 +9,9 @@ import Easing from './Easing' import InterTween from 'intertween' import NodeCache from './NodeCache' import EventClass from './Event' +import { create } from '../shim' + +Object.create = create // Events list export const EVENT_UPDATE = 'update' @@ -26,6 +29,22 @@ let _id = 0 // Unique ID const defaultEasing = Easing.Linear.None class Tween extends EventClass { + static fromTo (node, object, to, params = {}) { + params.quickRender = params.quickRender ? params.quickRender : !to + let tween = new Tween(node, object).to(to, params) + if (params.quickRender) { + tween.render().update(tween._startTime) + tween._rendered = false + tween._onStartCallbackFired = false + } + return tween + } + static to (node, to, params) { + return Tween.fromTo(node, null, to, params) + } + static from (node, from, params) { + return Tween.fromTo(node, from, null, params) + } constructor (node, object) { super() @@ -44,6 +63,7 @@ class Tween extends EventClass { let isArr = this.isArr = Array.isArray(object) this._valuesStart = isArr ? [] : {} this._valuesEnd = null + this._valuesFunc = {} this._duration = 1000 this._easingFunction = defaultEasing @@ -59,6 +79,7 @@ class Tween extends EventClass { this._onStartCallbackFired = false this._pausedTime = null this._isFinite = true + this._elapsed = 0 return this } @@ -145,8 +166,9 @@ class Tween extends EventClass { this._duration = typeof (duration) === 'function' ? duration(this._duration) : duration } else if (typeof duration === 'object') { for (let prop in duration) { - if (this[prop]) { - this[prop](...(Array.isArray(duration) ? duration : [duration])) + if (typeof this[prop] === 'function') { + let [arg1, arg2, arg3, arg4] = Array.isArray(duration[prop]) ? duration[prop] : [duration[prop]] + this[prop](arg1, arg2, arg3, arg4) } } } @@ -161,29 +183,40 @@ class Tween extends EventClass { let { _valuesEnd, + _valuesFunc, _valuesStart, object, - Renderer + Renderer, + node, + InitialValues } = this + if (node && InitialValues) { + if (!object) { + object = this.object = NodeCache(node, InitialValues(node, _valuesEnd)) + } else if (!_valuesEnd) { + _valuesEnd = this._valuesEnd = InitialValues(node, object) + } + } + for (let property in _valuesEnd) { let start = object[property] let end = _valuesEnd[property] if (Plugins[property]) { - _valuesEnd[property] = new Plugins[property](this, start, end) + _valuesFunc[property] = new Plugins[property](this, start, end) continue } - if (object[property] === undefined) { + if (!object || object[property] === undefined) { continue } - if (typeof start === 'number' && typeof end === 'number') { + if (typeof end === 'number' && typeof start === 'number') { _valuesStart[property] = start _valuesEnd[property] = end } else { - _valuesEnd[property] = InterTween(start, end) + _valuesFunc[property] = InterTween(start, end) } } @@ -208,28 +241,23 @@ class Tween extends EventClass { stop () { let { _isPlaying, - object + object, + _startTime, + _duration } = this if (!_isPlaying) { return this } + this.update(_startTime + _duration) + remove(this) this._isPlaying = false return this.emit(EVENT_STOP, object) } - end () { - const { - _startTime, - _duration - } = this - - return this.update(_startTime + _duration) - } - delay (amount) { this._delayTime = typeof (amount) === 'function' ? amount(this._delayTime) : amount this._startTime += this._delayTime @@ -309,8 +337,10 @@ class Tween extends EventClass { _duration, _valuesStart, _valuesEnd, + _valuesFunc, object, _isFinite, + _isPlaying, __render } = this @@ -320,7 +350,7 @@ class Tween extends EventClass { time = time !== undefined ? time : now() - if (time < _startTime) { + if (!_isPlaying || time < _startTime) { return true } @@ -339,18 +369,25 @@ class Tween extends EventClass { elapsed = elapsed > 1 ? 1 : elapsed elapsed = _reversed ? 1 - elapsed : elapsed + if (!object) { + return true + } + for (property in _valuesEnd) { value = _easingFunction[property] ? _easingFunction[property](elapsed) : typeof _easingFunction === 'function' ? _easingFunction(elapsed) : defaultEasing(elapsed) let start = _valuesStart[property] let end = _valuesEnd[property] + let fnc = _valuesFunc[property] - if (end.update) { - end.update(value, elapsed) + if (fnc && fnc.update) { + fnc.update(value, elapsed) + } else if (fnc) { + object[property] = fnc(value) } else if (typeof end === 'number') { object[property] = start + (end - start) * value - } else if (typeof end === 'function') { - object[property] = end(value) + } else { + object[property] = end } } @@ -385,8 +422,10 @@ class Tween extends EventClass { if (!preserve) { remove(this) } + this._isPlaying = false this.emit(EVENT_COMPLETE, object) this._repeat = this._r + _id-- return false } diff --git a/src/dist/core.js b/src/dist/core.js index 1e8baf8..24b0419 100644 --- a/src/dist/core.js +++ b/src/dist/core.js @@ -1,12 +1,12 @@ /* global process */ -import { root } from '../shim' +import { root, requestAnimationFrame, cancelAnimationFrame } from '../shim' let _tweens = [] let isStarted = false let _autoPlay = false let _tick -const _ticker = root.requestAnimationFrame -const _stopTicker = root.cancelAnimationFrame +const _ticker = requestAnimationFrame +const _stopTicker = cancelAnimationFrame const add = tween => { _tweens.push(tween) diff --git a/src/shim.js b/src/shim.js index 4e187a5..b5bcc90 100644 --- a/src/shim.js +++ b/src/shim.js @@ -1,28 +1,20 @@ /* global global */ -export let root = typeof (window) !== 'undefined' ? window : typeof (global) !== 'undefined' ? global : this - -if (!Object.assign) { - Object.assign = (source, ...args) => { - for (let i = 0, len = args.length; i < len; i++) { - let arg = args[i] - for (let p in arg) { - source[p] = arg[p] - } - } - return source - } +export let create = Object.create || function (source) { + return Object.assign({}, source || {}) } -if (!Object.create) { - Object.create = source => { - return Object.assign({}, source || {}) +export let assign = Object.assign || function (source, ...args) { + for (let i = 0, len = args.length; i < len; i++) { + let arg = args[i] + for (let p in arg) { + source[p] = arg[p] + } } + return source } + if (!Array.isArray) { Array.isArray = source => source && source.push && source.splice } -if (typeof (requestAnimationFrame) === 'undefined') { - root.requestAnimationFrame = fn => root.setTimeout(fn, 16) -} -if (typeof (cancelAnimationFrame) === 'undefined') { - root.cancelAnimationFrame = id => root.clearTimeout(id) -} +export let root = typeof (window) !== 'undefined' ? window : typeof (global) !== 'undefined' ? global : this +export let requestAnimationFrame = root.requestAnimationFrame || function (fn) { return root.setTimeout(fn, 16) } +export let cancelAnimationFrame = root.cancelAnimationFrame || function (id) { return root.clearTimeout(id) } diff --git a/test.js b/test.js index aac211c..a99ab38 100644 --- a/test.js +++ b/test.js @@ -46,7 +46,7 @@ test('Events', t => { test('Value Interpolation', t => { - let obj = { a: 0, b: 'B value 1', c: { x: 2 }, d: [3], _e: 4 } + let obj = { a: 0, b: 'B value 1', c: { x: 2 }, d: [3], _e: 4, g: 5 } Object.defineProperty(obj, 'e', { get: () => obj._e, @@ -54,7 +54,7 @@ test('Value Interpolation', t => { }) let tween = new Tween(obj) - .to({ a: 1, b: 'B value 2', c: { x: 3 }, d: [4], _e: 5 }, 100) + .to({ a: 1, b: 'B value 2', c: { x: 3 }, d: [4], _e: 5, g: '+=1' }, 100) .start(0) update(0) @@ -64,6 +64,7 @@ test('Value Interpolation', t => { t.is(obj.c.x, 2) t.is(obj.d[0], 3) t.is(obj.e, 4) + t.is(obj.g, 5) update(50) @@ -82,6 +83,9 @@ test('Value Interpolation', t => { t.is(obj.e, 4.5, 'Getter/Setter interpolation not worked as excepted') t.log('Getter/Setter interpolation worked as excepted') + t.is(obj.g, 5.5, 'Relative number interpolation not worked as excepted') + t.log('Relative number interpolation worked as excepted') + update(100) @@ -90,14 +94,15 @@ test('Value Interpolation', t => { t.is(obj.c.x, 3) t.is(obj.d[0], 4) t.is(obj.e, 5) + t.is(obj.g, 6) }) test('Value Array-based Interpolation', t => { - let obj = { x: 0 } + let obj = { x: 0, y: [2, 4, 6] } let tween = new Tween(obj) - .to({ x: [1, 3, 5] }, 100) + .to({ x: [1, 3, 5], y: 10 }, 100) .start(0) t.is(obj.x, 0) @@ -107,6 +112,9 @@ test('Value Array-based Interpolation', t => { t.is(obj.x, 2, 'Interpolation failed') t.log('End-value interpolation was done') + t.deepEqual(obj.y, [6, 7, 8], 'Tween-them failed') + t.log('Start-value interpolation was done') + tween.update(100) })