From 43c7f716b48420dc4401374899cfa56fdf4b47af Mon Sep 17 00:00:00 2001 From: Davlat Date: Fri, 24 Nov 2017 12:23:25 +0500 Subject: [PATCH] * docs(CODE_OF_CONDUCT): added * code(lint): some files was linted * code(Tween.ts): removed `@extends` to fix doc * feat(Interpolation.ts): new method for accessing via plug-ins --- CODE_OF_CONDUCT.md | 4 + examples/basic.html | 44 +++---- package-lock.json | 61 +--------- package.json | 2 +- ts/Easing.ts | 2 +- ts/Interpolation.ts | 280 ++++++++++++++++++++++++++++++-------------- ts/Interpolator.ts | 47 ++++++++ ts/Tween.ts | 79 +++++++++---- ts/constants.ts | 101 ++++++++++++---- ts/index.ts | 2 + 10 files changed, 404 insertions(+), 218 deletions(-) create mode 100644 ts/Interpolator.ts diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d32d7fb..b78e737 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -43,4 +43,8 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org +<<<<<<< HEAD [version]: http://contributor-covenant.org/version/1/4/ +======= +[version]: http://contributor-covenant.org/version/1/4/ +>>>>>>> c51a062... * docs(CODE_OF_CONDUCT): added diff --git a/examples/basic.html b/examples/basic.html index dc5137a..777c007 100644 --- a/examples/basic.html +++ b/examples/basic.html @@ -13,37 +13,37 @@ text-align: center; line-height: 5em; } -.box { - width: 50px; - height: 50px; - background: #fc0; -} -
- - - - +
+
- - \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 39583de..b6d5589 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "es6-tween", - "version": "4.0.1", + "version": "4.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1409,30 +1409,6 @@ "integrity": "sha1-BcOlDYMYmYFpnuDAdtOjlQ237AA=", "dev": true }, - "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", - "dev": true, - "requires": { - "esutils": "1.1.6", - "isarray": "0.0.1" - }, - "dependencies": { - "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", @@ -2337,6 +2313,9 @@ "walk-back": "3.0.0" } }, + "jsdoc-typescript-plugin": { + "version": "git+https://github.com/jumpinjackie/jsdoc-typescript-plugin.git#a12832a399311c6fd1014a58ab40ba2c9af5eb90" + }, "jsdoc2md-stats": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jsdoc2md-stats/-/jsdoc2md-stats-2.0.1.tgz", @@ -3956,38 +3935,6 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "tslib": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==", - "dev": true - }, - "tslint-config-standard": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tslint-config-standard/-/tslint-config-standard-7.0.0.tgz", - "integrity": "sha512-QCrLt8WwiRgZpRSgRsk6cExy8/Vipa/5fHespm4Q1ly90EB6Lni04Ub8dkEW10bV3fPN3SkxEwj41ZOe/knCZA==", - "dev": true, - "requires": { - "tslint-eslint-rules": "4.1.1" - } - }, - "tslint-eslint-rules": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz", - "integrity": "sha1-fDDniC8mvCdr/5HSOEl1xp2viLo=", - "dev": true, - "requires": { - "doctrine": "0.7.2", - "tslib": "1.8.0", - "tsutils": "1.9.1" - } - }, - "tsutils": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", - "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", - "dev": true - }, "typescript": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz", diff --git a/package.json b/package.json index df62d48..bd8efe5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "es6-tween", - "version": "4.1.0", + "version": "4.2.0", "description": "ES6 implementation of amazing tween.js", "browser": "full/Tween.min.js", "cdn": "full/Tween.min.js", diff --git a/ts/Easing.ts b/ts/Easing.ts index aeeb488..79154db 100644 --- a/ts/Easing.ts +++ b/ts/Easing.ts @@ -238,7 +238,7 @@ const Easing = { } return Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5; - }, + } }, Stepped: { diff --git a/ts/Interpolation.ts b/ts/Interpolation.ts index 7614b6b..52fb1ee 100644 --- a/ts/Interpolation.ts +++ b/ts/Interpolation.ts @@ -1,3 +1,5 @@ +import { isRGBColor, RGBA, recompose, STRING_PROP } from './constants'; + /** * List of full Interpolation * @namespace TWEEN.Interpolation @@ -9,134 +11,240 @@ * @memberof TWEEN */ const Interpolation = { - - Linear (v, k, value) { - const m = v.length - 1 - const f = m * k - const i = Math.floor(f) - const fn = Interpolation.Utils.Linear - + Linear(v, k, value) { + const m = v.length - 1; + const f = m * k; + const i = Math.floor(f); + const fn = Interpolation.Utils.Linear; if (k < 0) { - return fn(v[0], v[1], f, value) + return fn(v[0], v[1], f, value); } - if (k > 1) { - return fn(v[m], v[m - 1], m - f, value) + return fn(v[m], v[m - 1], m - f, value); } - - return fn(v[i], v[i + 1 > m ? m : i + 1], f - i, value) + return fn(v[i], v[i + 1 > m ? m : i + 1], f - i, value); }, - Bezier (v, k, value) { - let b = 0 - const n = v.length - 1 - const pw = Math.pow - const bn = Interpolation.Utils.Bernstein + Bezier(v, k, value) { + let b = Interpolation.Utils.Reset(value); + let n = v.length - 1; + let pw = Math.pow; + let fn = Interpolation.Utils.Bernstein; + + let isBArray = Array.isArray(b); for (let i = 0; i <= n; i++) { - b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i) + if (typeof b === 'number') { + b += pw(1 - k, n - i) * pw(k, i) * v[i] * fn(n, i); + } else if (isBArray) { + for (let p = 0, len = b.length; p < len; p++) { + if (typeof b[p] === 'number') { + b[p] += pw(1 - k, n - i) * pw(k, i) * v[i][p] * fn(n, i); + } else { + b[p] = v[i][p]; + } + } + } else if (typeof b === 'object') { + for (let p in b) { + if (typeof b[p] === 'number') { + b[p] += pw(1 - k, n - i) * pw(k, i) * v[i][p] * fn(n, i); + } else { + b[p] = v[i][p]; + } + } + } else if (typeof b === 'string') { + let STRING_BUFFER = '', + idx = Math.round(n * k), + pidx = idx - 1 < 0 ? 0 : idx - 1, + nidx = idx + 1 > n ? n : idx + 1, + vCurr = v[idx], + vPrev = v[pidx]; + for (let ks = 1, len = vCurr.length; ks < len; ks++) { + STRING_BUFFER += vCurr[ks]; + } + return STRING_BUFFER; + } } - return b + return b; }, - CatmullRom (v, k, value) { - const m = v.length - 1 - let f = m * k - let i = Math.floor(f) - const fn = Interpolation.Utils.CatmullRom + CatmullRom(v, k, value) { + const m = v.length - 1; + let f = m * k; + let i = Math.floor(f); + const fn = Interpolation.Utils.CatmullRom; if (v[0] === v[m]) { if (k < 0) { - i = Math.floor(f = m * (1 + k)) + i = Math.floor((f = m * (1 + k))); } - return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i, value) + return fn( + v[(i - 1 + m) % m], + v[i], + v[(i + 1) % m], + v[(i + 2) % m], + f - i, + value + ); } else { if (k < 0) { - return v[0] - (fn(v[0], v[0], v[1], v[1], -f, value) - v[0]) + return fn(v[1], v[1], v[0], v[0], -k, value); } if (k > 1) { - return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m, value) - v[m]) + return fn(v[m - 1], v[m - 1], v[m], v[m], (k | 0) - k, value); } - return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i, value) + return fn( + v[i ? i - 1 : 0], + v[i], + v[m < i + 1 ? m : i + 1], + v[m < i + 2 ? m : i + 2], + f - i, + value + ); } }, Utils: { + Linear(p0, p1, t, v) { + if (typeof p0 === 'string') { + return p1; + } else if (typeof p0 === 'number') { + return typeof p0 === 'function' ? p0(t) : p0 + (p1 - p0) * t; + } else if (typeof p0 === 'object') { + if (p0.length !== undefined) { + if (p0[0] === STRING_PROP) { + let STRING_BUFFER = ''; + for (let i = 1, len = p0.length; i < len; i++) { + let currentValue = + typeof p0[i] === 'number' ? p0[i] + (p1[i] - p0[i]) * t : p1[i]; + if (isRGBColor(p0, i) || isRGBColor(p0, i, RGBA)) { + currentValue |= 0; + } + STRING_BUFFER += currentValue; + } + return STRING_BUFFER; + } + for (let p = 0, len = v.length; p < len; p++) { + v[p] = Interpolation.Utils.Linear(p0[p], p1[p], t, v[p]); + } + } else { + for (const p in v) { + v[p] = Interpolation.Utils.Linear(p0[p], p1[p], t, v[p]); + } + } + return v; + } + }, - Linear (p0, p1, t, v) { - if (typeof v === 'string') { - return p1 - } else if (typeof v === 'number') { - return typeof p0 === 'function' ? p0(t) : (p1 - p0) * t + p0 - } else if (typeof v === 'object') { - if (v.length !== undefined) { - for (let p = 0, len = v.length; p < len; p++) { - v[p] = Interpolation.Utils.Linear(p0[p], p1[p], t, v[p]) - } - } else { - for (const p in v) { - v[p] = Interpolation.Utils.Linear(p0[p], p1[p], t, v[p]) - } - } - return v - } + Reset(value) { + if (Array.isArray(value)) { + for (let i = 0, len = value.length; i < len; i++) { + value[i] = Interpolation.Utils.Reset(value[i]); + } + return value; + } else if (typeof value === 'object') { + for (let i in value) { + value[i] = Interpolation.Utils.Reset(value[i]); + } + return value; + } else if (typeof value === 'number') { + return 0; + } + return value; }, - Bernstein (n, i) { - const fc = Interpolation.Utils.Factorial + Bernstein(n, i) { + const fc = Interpolation.Utils.Factorial; - return fc(n) / fc(i) / fc(n - i) + return fc(n) / fc(i) / fc(n - i); }, - Factorial: (function () { - const a = [1] + Factorial: (function() { + const a = [1]; - return (n) => { - let s = 1 + return n => { + let s = 1; if (a[n]) { - return a[n] + return a[n]; } for (let i = n; i > 1; i--) { - s *= i + s *= i; } - a[n] = s - return s - } + a[n] = s; + return s; + }; })(), - CatmullRom (p0, p1, p2, p3, t, v) { - if (typeof v === 'string') { - return p1 - } else if (typeof v === 'number') { - const v0 = (p2 - p0) * 0.5 - const v1 = (p3 - p1) * 0.5 - const t2 = t * t - const t3 = t * t2 - - return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1 - } else if (typeof v === 'object') { - if (v.length !== undefined) { - for (let p = 0, len = v.length; p < len; p++) { - v[p] = Interpolation.Utils.CatmullRom(p0[p], p1[p], p2[p], p3[p], t, v[p]) - } - } else { - for (const p in v) { - v[p] = Interpolation.Utils.CatmullRom(p0[p], p1[p], p2[p], p3[p], t, v[p]) - } - } - return v - } - } - - } - -} + CatmullRom(p0, p1, p2, p3, t, v?) { + if (typeof p0 === 'string') { + return p1; + } else if (typeof p0 === 'number') { + const v0 = (p2 - p0) * 0.5; + const v1 = (p3 - p1) * 0.5; + const t2 = t * t; + const t3 = t * t2; + + return ( + (2 * p1 - 2 * p2 + v0 + v1) * t3 + + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + + v0 * t + + p1 + ); + } else if (typeof p0 === 'object') { + if (p0.length !== undefined) { + if (p0[0] === STRING_PROP) { + let STRING_BUFFER = ''; + for (let i = 1, len = p0.length; i < len; i++) { + let currentValue = + typeof p0[i] === 'number' + ? Interpolation.Utils.CatmullRom( + p0[i], + p1[i], + p2[i], + p3[i], + t + ) + : p3[i]; + if (isRGBColor(p0, i) || isRGBColor(p0, i, RGBA)) { + currentValue |= 0; + } + STRING_BUFFER += currentValue; + } + return STRING_BUFFER; + } + for (let p = 0, len = v.length; p < len; p++) { + v[p] = Interpolation.Utils.CatmullRom( + p0[p], + p1[p], + p2[p], + p3[p], + t, + v[p] + ); + } + } else { + for (const p in v) { + v[p] = Interpolation.Utils.CatmullRom( + p0[p], + p1[p], + p2[p], + p3[p], + t, + v[p] + ); + } + } + return v; + } + }, + }, +}; -export default Interpolation +export default Interpolation; diff --git a/ts/Interpolator.ts b/ts/Interpolator.ts new file mode 100644 index 0000000..a3210c2 --- /dev/null +++ b/ts/Interpolator.ts @@ -0,0 +1,47 @@ +import { decompose, recompose, decomposeString, STRING_PROP } from './constants' + +const Interpolator = (a: any, b: any): Function => { + let isArray: boolean = Array.isArray(a); + let origin: any = typeof a === 'string' ? a : isArray ? a.slice() : Object.assign({}, a); + if (isArray) { + for (let i = 0, len = a.length; i < len; i++) { + decompose(i, origin, a, b) + } + } else if (typeof a === 'object') { + for (let i in a) { + decompose(i, origin, a, b) + } + } else if (typeof a === 'string') { + a = decomposeString(a) + b = decomposeString(b) + + let i = 1; + while (i < a.length) { + if (a[i] === b[i] && typeof a[i - 1] === 'string') { + a.splice(i - 1, 2, a[i - 1] + a[i]) + b.splice(i - 1, 2, b[i - 1] + b[i]) + } else { + i++ + } + } + + a.unshift(STRING_PROP) + b.unshift(STRING_PROP) + } + return function (t: number) { + if (isArray) { + for (let i = 0, len = a.length; i < len; i++) { + recompose(i, origin, a, b, t) + } + } else if (typeof origin === 'object') { + for (let i in a) { + recompose(i, origin, a, b, t) + } + } else if (typeof origin === 'string') { + origin = recompose(0, 0, a, b, t, t, true) + } + return origin; + } +} + +export default Interpolator \ No newline at end of file diff --git a/ts/Tween.ts b/ts/Tween.ts index 04af11d..28609e2 100644 --- a/ts/Tween.ts +++ b/ts/Tween.ts @@ -5,9 +5,11 @@ import NodeCache, { Store } from './NodeCache'; import Selector from './selector'; import { decompose, + decomposeString, recompose, deepCopy, SET_NESTED, + STRING_PROP, EVENT_CALLBACK, CHAINED_TWEENS, EVENT_UPDATE, @@ -32,16 +34,11 @@ export interface Params { quickRender?: boolean; } -export interface RenderType { - update?: Function; -} - /** * Tween main constructor * @constructor * @class * @namespace Tween - * @extends Tween * @param {Object|Element} node Node Element or Tween initial object * @param {Object=} object If Node Element is using, second argument is used for Tween initial object * @example let tween = new Tween(myNode, {width:'100px'}).to({width:'300px'}, 2000).start() @@ -63,7 +60,6 @@ class Tween { public _yoyo: boolean; public _pausedTime: number; public node: any; - public Renderer: any; public _r: number; public _reversed: boolean; public _isFinite: boolean; @@ -71,7 +67,8 @@ class Tween { public elapsed: number; private _onStartCallbackFired: boolean; private _rendered: boolean; - private __render: RenderType; + private __render: boolean; + public static Renderer: any; private InitialValues: any; private _maxListener: number; private _chainedTweensCount: number = 0; @@ -432,7 +429,6 @@ class Tween { _valuesStart, _valuesEnd, object, - Renderer, node, InitialValues, _easingFunction, @@ -469,21 +465,23 @@ class Tween { } } for (const property in _valuesEnd) { - const start = object && object[property]; - const end = _valuesEnd[property]; - if (Plugins[property]) { - const plugin = Plugins[property].prototype.update - ? new Plugins[property](this, start, end, property, object) - : Plugins[property](this, start, end, property, object); - if (plugin) { - _valuesEnd[property] = plugin; + let start = object && object[property] && deepCopy(object[property]); + let end = _valuesEnd[property]; + if (Plugins[property] && Plugins[property].init) { + Plugins[property].init.call(this, start, end, property, object); + if (start === undefined && _valuesStart[property]) { + start = _valuesStart[property]; + } + if (Plugins[property].skipProcess) { + continue; } - continue; } if ( (typeof start === 'number' && isNaN(start)) || start === null || end === null || + start === false || + end === false || start === undefined || end === undefined || start === end @@ -492,13 +490,20 @@ class Tween { } if (Array.isArray(end) && !Array.isArray(start)) { end.unshift(start); + for (let i = 0, len = end.length; i < len; i++) { + if (typeof end[i] === 'string') { + end[i] = decomposeString(end[i]); + end[i].unshift(STRING_PROP); + } + } } - _valuesStart[property] = deepCopy(start); + _valuesStart[property] = start; decompose(property, object, _valuesStart, _valuesEnd); } - if (Renderer && this.node) { - this.__render = new Renderer(this, object, _valuesEnd); + if (Tween.Renderer && this.node && Tween.Renderer.init) { + Tween.Renderer.init.call(this, object, _valuesStart, _valuesEnd); + this.__render = true; } return this; @@ -734,10 +739,10 @@ class Tween { time = time !== undefined ? time : now(); let delta: number = time - _prevTime; + this._prevTime = time; if (delta > TOO_LONG_FRAME_MS) { - time += delta - FRAME_MS; + time -= delta - FRAME_MS; } - this._prevTime = time; if (!_isPlaying || (time < _startTime && !forceTime)) { return true; @@ -769,7 +774,10 @@ class Tween { for (property in _valuesEnd) { const start = _valuesStart[property]; - if (start === undefined || start === null) { + if ( + (start === undefined || start === null) && + !(Plugins[property] && Plugins[property].update) + ) { continue; } const end = _valuesEnd[property]; @@ -778,12 +786,21 @@ class Tween { : typeof currentEasing === 'function' ? currentEasing(elapsed) : defaultEasing(elapsed); + const _interpolationFunctionCall = _interpolationFunction[property] + ? _interpolationFunction[property] + : typeof _interpolationFunction === 'function' + ? _interpolationFunction + : Interpolation.Linear; if (typeof end === 'number') { object[property] = (((start + (end - start) * value) * DECIMAL) | 0) / DECIMAL; } else if (Array.isArray(end) && !Array.isArray(start)) { - object[property] = _interpolationFunction(end, value, object[property]); + object[property] = _interpolationFunctionCall( + end, + value, + object[property] + ); } else if (end && end.update) { end.update(value); } else if (typeof end === 'function') { @@ -791,6 +808,16 @@ class Tween { } else { recompose(property, object, _valuesStart, _valuesEnd, value, elapsed); } + if (Plugins[property] && Plugins[property].update) { + Plugins[property].update.call( + this, + object[property], + start, + end, + value, + elapsed + ); + } propCount++; } @@ -799,8 +826,8 @@ class Tween { return false; } - if (__render) { - __render.update(object, elapsed); + if (__render && Tween.Renderer && Tween.Renderer.update) { + Tween.Renderer.update.call(this, object, elapsed); } this.emit(EVENT_UPDATE, object, elapsed, time); diff --git a/ts/constants.ts b/ts/constants.ts index 0af418e..7be4105 100644 --- a/ts/constants.ts +++ b/ts/constants.ts @@ -20,12 +20,12 @@ export const EVENT_SEEK = 'seek'; // For String tweening stuffs export const STRING_PROP = 'STRING_PROP'; // Also RegExp's for string tweening -export const NUM_REGEX = /\s+|([A-Za-z?().,{}:""[\]#\%]+)|([-+]+)?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; +export const NUM_REGEX = /\s+|([A-Za-z?().,{}:""[\]#\%]+)|([-+]=+)?([-+]+)?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]=?\d+)?/g; export const HEXC_REGEX = /^#([0-9a-f]{6}|[0-9a-f]{3})$/i; // Copies everything, duplicates, no shallow-copy export function deepCopy(source) { - if (source === undefined || typeof source !== 'object') { + if ((source && source.nodeType) || source === undefined || typeof source !== 'object') { return source; } else if (Array.isArray(source)) { return [].concat(source); @@ -40,20 +40,56 @@ export function deepCopy(source) { } const isNaNForST = v => - isNaN(+v) || v[0] === '+' || v[0] === '-' || v === '' || v === ' '; + isNaN(+v) || ((v[0] === '+' || v[0] === '-') && v[1] === '=') || v === '' || v === ' '; + +const hexColor = /^#([0-9a-f]{6}|[0-9a-f]{3})$/i; +const hex2rgb = (all, hex) => { + let r; + let g; + let b; + if (hex.length === 3) { + r = hex[0]; + g = hex[1]; + b = hex[2]; + hex = r + r + g + g + b + b; + } + let color = parseInt(hex, 16); + r = color >> 16 & 255; + g = color >> 8 & 255; + b = color & 255; + return "rgb(" + r + "," + g + "," + b + ")"; +}; + +export function decomposeString(fromValue: string): any[] { + return fromValue.replace(hexColor, hex2rgb).match(NUM_REGEX).map(v => (isNaNForST(v) ? v : +v)); +} // Decompose value, now for only `string` that required -export function decompose(prop, obj, from, to) { +export function decompose(prop, obj, from, to, stringBuffer?) { const fromValue = from[prop]; const toValue = to[prop]; - if (typeof fromValue === 'string' && typeof toValue === 'string') { - let fromValue1 = fromValue - .match(NUM_REGEX) - .map(v => (isNaNForST(v) ? v : +v)); - let toValue1 = toValue - .match(NUM_REGEX) - .map((v, i) => (isNaNForST(v) ? v : +v)); + + if (typeof fromValue === 'string' || typeof toValue === 'string') { + let fromValue1 = Array.isArray(fromValue) && fromValue[0] === STRING_PROP ? fromValue : decomposeString(fromValue); + let toValue1 = Array.isArray(toValue) && toValue[0] === STRING_PROP ? toValue : decomposeString(toValue); + + let i = 1; + while (i < fromValue1.length) { + if (fromValue1[i] === toValue1[i] && typeof fromValue1[i - 1] === 'string') { + fromValue1.splice(i - 1, 2, fromValue1[i - 1] + fromValue1[i]) + toValue1.splice(i - 1, 2, toValue1[i - 1] + toValue1[i]) + } else { + i++ + } + } + + if (fromValue1[0] !== STRING_PROP) { fromValue1.unshift(STRING_PROP); + } + if (toValue1[0] !== STRING_PROP) { + toValue1.unshift(STRING_PROP); + } + from[prop] = fromValue1; to[prop] = toValue1; return true; @@ -74,9 +110,15 @@ export function decompose(prop, obj, from, to) { // Recompose value export const DECIMAL = Math.pow(10, 4); -export function recompose(prop, obj, from, to, t, originalT?) { - const fromValue = from[prop]; - const toValue = to[prop]; +export const RGB = 'rgb('; +export const RGBA = 'rgba('; + +export const isRGBColor = (v, i, r = RGB) => + typeof v[i] === 'number' && + (v[i - 1] === r || v[i - 3] === r || v[i - 5] === r); +export function recompose(prop, obj, from, to, t, originalT?, stringBuffer?) { + const fromValue = stringBuffer ? from : from[prop]; + const toValue = stringBuffer ? to : to[prop]; if (toValue === undefined) { return fromValue; } @@ -90,33 +132,42 @@ export function recompose(prop, obj, from, to, t, originalT?) { if (!fromValue || !toValue) { return obj[prop]; } - if (fromValue[0] === STRING_PROP) { + if (fromValue[0] === STRING_PROP || toValue[0] === STRING_PROP) { let STRING_BUFFER = ''; for (let i = 1, len = fromValue.length; i < len; i++) { - const isRelative = typeof toValue[i - 1] === 'string'; - STRING_BUFFER += - typeof toValue[i - 1] !== 'number' + const isRelative = typeof fromValue[i] === 'number' && typeof toValue[i] === 'string' && toValue[i][1] === '='; + let currentValue = + typeof fromValue[i] !== 'number' ? fromValue[i] : (((isRelative - ? fromValue[i] + +toValue[i - 1] - : fromValue[i] + (toValue[i - 1] - fromValue[i]) * t) * + ? fromValue[i] + + parseFloat(toValue[i][0] + toValue[i].substr(2)) * t + : fromValue[i] + (toValue[i] - fromValue[i]) * t) * DECIMAL) | 0) / DECIMAL; - if (originalT === 1) { - fromValue[i] = fromValue[i] + +toValue[i - 1]; + if (isRGBColor(fromValue, i) || isRGBColor(fromValue, i, RGBA)) { + currentValue |= 0; + } + STRING_BUFFER += currentValue; + if (isRelative && originalT === 1) { + fromValue[i] = + fromValue[i] + + parseFloat(toValue[i][0] + toValue[i].substr(2)); } } + if (!stringBuffer) { obj[prop] = STRING_BUFFER; + } return STRING_BUFFER; - } else if (Array.isArray(fromValue)) { + } else if (Array.isArray(fromValue) && fromValue[0] !== STRING_PROP) { for (let i = 0, len = fromValue.length; i < len; i++) { if (fromValue[i] === toValue[i]) { continue; } recompose(i, obj[prop], fromValue, toValue, t, originalT); } - } else { + } else if (typeof fromValue === 'object' && !!fromValue) { for (let i in fromValue) { if (fromValue[i] === toValue[i]) { continue; @@ -128,7 +179,7 @@ export function recompose(prop, obj, from, to, t, originalT?) { const isRelative = typeof toValue === 'string'; obj[prop] = (((isRelative - ? fromValue + +toValue * t + ? fromValue + parseFloat(toValue[0] + toValue.substr(2)) * t : fromValue + (toValue - fromValue) * t) * DECIMAL) | 0) / diff --git a/ts/index.ts b/ts/index.ts index 4a893b8..c1d33b8 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -17,10 +17,12 @@ import Interpolation from './Interpolation'; import Timeline from './Timeline'; import Tween from './Tween'; import Selector from './selector'; +import Interpolator from './Interpolator'; import './shim'; export { Plugins, Selector, + Interpolator, onTick, has, get,