123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- import Clip from './Clip';
- import * as color from '../tool/color';
- import { isArrayLike, keys, logError } from '../core/util';
- var arraySlice = Array.prototype.slice;
- export function interpolateNumber(p0, p1, percent) {
- return (p1 - p0) * percent + p0;
- }
- export function step(p0, p1, percent) {
- return percent > 0.5 ? p1 : p0;
- }
- export function interpolate1DArray(out, p0, p1, percent) {
- var len = p0.length;
- for (var i = 0; i < len; i++) {
- out[i] = interpolateNumber(p0[i], p1[i], percent);
- }
- }
- export function interpolate2DArray(out, p0, p1, percent) {
- var len = p0.length;
- var len2 = len && p0[0].length;
- for (var i = 0; i < len; i++) {
- if (!out[i]) {
- out[i] = [];
- }
- for (var j = 0; j < len2; j++) {
- out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
- }
- }
- }
- function add1DArray(out, p0, p1, sign) {
- var len = p0.length;
- for (var i = 0; i < len; i++) {
- out[i] = p0[i] + p1[i] * sign;
- }
- return out;
- }
- function add2DArray(out, p0, p1, sign) {
- var len = p0.length;
- var len2 = len && p0[0].length;
- for (var i = 0; i < len; i++) {
- if (!out[i]) {
- out[i] = [];
- }
- for (var j = 0; j < len2; j++) {
- out[i][j] = p0[i][j] + p1[i][j] * sign;
- }
- }
- return out;
- }
- function fillArray(val0, val1, arrDim) {
- var arr0 = val0;
- var arr1 = val1;
- if (!arr0.push || !arr1.push) {
- return;
- }
- var arr0Len = arr0.length;
- var arr1Len = arr1.length;
- if (arr0Len !== arr1Len) {
- var isPreviousLarger = arr0Len > arr1Len;
- if (isPreviousLarger) {
- arr0.length = arr1Len;
- }
- else {
- for (var i = arr0Len; i < arr1Len; i++) {
- arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
- }
- }
- }
- var len2 = arr0[0] && arr0[0].length;
- for (var i = 0; i < arr0.length; i++) {
- if (arrDim === 1) {
- if (isNaN(arr0[i])) {
- arr0[i] = arr1[i];
- }
- }
- else {
- for (var j = 0; j < len2; j++) {
- if (isNaN(arr0[i][j])) {
- arr0[i][j] = arr1[i][j];
- }
- }
- }
- }
- }
- function is1DArraySame(arr0, arr1) {
- var len = arr0.length;
- if (len !== arr1.length) {
- return false;
- }
- for (var i = 0; i < len; i++) {
- if (arr0[i] !== arr1[i]) {
- return false;
- }
- }
- return true;
- }
- function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
- var v0 = (p2 - p0) * 0.5;
- var v1 = (p3 - p1) * 0.5;
- return (2 * (p1 - p2) + v0 + v1) * t3
- + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
- + v0 * t + p1;
- }
- function catmullRomInterpolate1DArray(out, p0, p1, p2, p3, t, t2, t3) {
- var len = p0.length;
- for (var i = 0; i < len; i++) {
- out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3);
- }
- }
- function catmullRomInterpolate2DArray(out, p0, p1, p2, p3, t, t2, t3) {
- var len = p0.length;
- var len2 = p0[0].length;
- for (var i = 0; i < len; i++) {
- if (!out[i]) {
- out[1] = [];
- }
- for (var j = 0; j < len2; j++) {
- out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3);
- }
- }
- }
- export function cloneValue(value) {
- if (isArrayLike(value)) {
- var len = value.length;
- if (isArrayLike(value[0])) {
- var ret = [];
- for (var i = 0; i < len; i++) {
- ret.push(arraySlice.call(value[i]));
- }
- return ret;
- }
- return arraySlice.call(value);
- }
- return value;
- }
- function rgba2String(rgba) {
- rgba[0] = Math.floor(rgba[0]);
- rgba[1] = Math.floor(rgba[1]);
- rgba[2] = Math.floor(rgba[2]);
- return 'rgba(' + rgba.join(',') + ')';
- }
- function guessArrayDim(value) {
- return isArrayLike(value && value[0]) ? 2 : 1;
- }
- var tmpRgba = [0, 0, 0, 0];
- var Track = (function () {
- function Track(propName) {
- this.keyframes = [];
- this.maxTime = 0;
- this.arrDim = 0;
- this.interpolable = true;
- this._needsSort = false;
- this._isAllValueEqual = true;
- this._lastFrame = 0;
- this._lastFramePercent = 0;
- this.propName = propName;
- }
- Track.prototype.isFinished = function () {
- return this._finished;
- };
- Track.prototype.setFinished = function () {
- this._finished = true;
- if (this._additiveTrack) {
- this._additiveTrack.setFinished();
- }
- };
- Track.prototype.needsAnimate = function () {
- return !this._isAllValueEqual
- && this.keyframes.length >= 2
- && this.interpolable
- && this.maxTime > 0;
- };
- Track.prototype.getAdditiveTrack = function () {
- return this._additiveTrack;
- };
- Track.prototype.addKeyframe = function (time, value) {
- if (time >= this.maxTime) {
- this.maxTime = time;
- }
- else {
- this._needsSort = true;
- }
- var keyframes = this.keyframes;
- var len = keyframes.length;
- if (this.interpolable) {
- if (isArrayLike(value)) {
- var arrayDim = guessArrayDim(value);
- if (len > 0 && this.arrDim !== arrayDim) {
- this.interpolable = false;
- return;
- }
- if (arrayDim === 1 && typeof value[0] !== 'number'
- || arrayDim === 2 && typeof value[0][0] !== 'number') {
- this.interpolable = false;
- return;
- }
- if (len > 0) {
- var lastFrame = keyframes[len - 1];
- if (this._isAllValueEqual) {
- if (arrayDim === 1) {
- if (!is1DArraySame(value, lastFrame.value)) {
- this._isAllValueEqual = false;
- }
- }
- else {
- this._isAllValueEqual = false;
- }
- }
- }
- this.arrDim = arrayDim;
- }
- else {
- if (this.arrDim > 0) {
- this.interpolable = false;
- return;
- }
- if (typeof value === 'string') {
- var colorArray = color.parse(value);
- if (colorArray) {
- value = colorArray;
- this.isValueColor = true;
- }
- else {
- this.interpolable = false;
- }
- }
- else if (typeof value !== 'number' || isNaN(value)) {
- this.interpolable = false;
- return;
- }
- if (this._isAllValueEqual && len > 0) {
- var lastFrame = keyframes[len - 1];
- if (this.isValueColor && !is1DArraySame(lastFrame.value, value)) {
- this._isAllValueEqual = false;
- }
- else if (lastFrame.value !== value) {
- this._isAllValueEqual = false;
- }
- }
- }
- }
- var kf = {
- time: time,
- value: value,
- percent: 0
- };
- this.keyframes.push(kf);
- return kf;
- };
- Track.prototype.prepare = function (additiveTrack) {
- var kfs = this.keyframes;
- if (this._needsSort) {
- kfs.sort(function (a, b) {
- return a.time - b.time;
- });
- }
- var arrDim = this.arrDim;
- var kfsLen = kfs.length;
- var lastKf = kfs[kfsLen - 1];
- for (var i = 0; i < kfsLen; i++) {
- kfs[i].percent = kfs[i].time / this.maxTime;
- if (arrDim > 0 && i !== kfsLen - 1) {
- fillArray(kfs[i].value, lastKf.value, arrDim);
- }
- }
- if (additiveTrack
- && this.needsAnimate()
- && additiveTrack.needsAnimate()
- && arrDim === additiveTrack.arrDim
- && this.isValueColor === additiveTrack.isValueColor
- && !additiveTrack._finished) {
- this._additiveTrack = additiveTrack;
- var startValue = kfs[0].value;
- for (var i = 0; i < kfsLen; i++) {
- if (arrDim === 0) {
- if (this.isValueColor) {
- kfs[i].additiveValue =
- add1DArray([], kfs[i].value, startValue, -1);
- }
- else {
- kfs[i].additiveValue = kfs[i].value - startValue;
- }
- }
- else if (arrDim === 1) {
- kfs[i].additiveValue = add1DArray([], kfs[i].value, startValue, -1);
- }
- else if (arrDim === 2) {
- kfs[i].additiveValue = add2DArray([], kfs[i].value, startValue, -1);
- }
- }
- }
- };
- Track.prototype.step = function (target, percent) {
- if (this._finished) {
- return;
- }
- if (this._additiveTrack && this._additiveTrack._finished) {
- this._additiveTrack = null;
- }
- var isAdditive = this._additiveTrack != null;
- var valueKey = isAdditive ? 'additiveValue' : 'value';
- var keyframes = this.keyframes;
- var kfsNum = this.keyframes.length;
- var propName = this.propName;
- var arrDim = this.arrDim;
- var isValueColor = this.isValueColor;
- var frameIdx;
- if (percent < 0) {
- frameIdx = 0;
- }
- else if (percent < this._lastFramePercent) {
- var start = Math.min(this._lastFrame + 1, kfsNum - 1);
- for (frameIdx = start; frameIdx >= 0; frameIdx--) {
- if (keyframes[frameIdx].percent <= percent) {
- break;
- }
- }
- frameIdx = Math.min(frameIdx, kfsNum - 2);
- }
- else {
- for (frameIdx = this._lastFrame; frameIdx < kfsNum; frameIdx++) {
- if (keyframes[frameIdx].percent > percent) {
- break;
- }
- }
- frameIdx = Math.min(frameIdx - 1, kfsNum - 2);
- }
- var nextFrame = keyframes[frameIdx + 1];
- var frame = keyframes[frameIdx];
- if (!(frame && nextFrame)) {
- return;
- }
- this._lastFrame = frameIdx;
- this._lastFramePercent = percent;
- var range = (nextFrame.percent - frame.percent);
- if (range === 0) {
- return;
- }
- var w = (percent - frame.percent) / range;
- var targetArr = isAdditive ? this._additiveValue
- : (isValueColor ? tmpRgba : target[propName]);
- if ((arrDim > 0 || isValueColor) && !targetArr) {
- targetArr = this._additiveValue = [];
- }
- if (this.useSpline) {
- var p1 = keyframes[frameIdx][valueKey];
- var p0 = keyframes[frameIdx === 0 ? frameIdx : frameIdx - 1][valueKey];
- var p2 = keyframes[frameIdx > kfsNum - 2 ? kfsNum - 1 : frameIdx + 1][valueKey];
- var p3 = keyframes[frameIdx > kfsNum - 3 ? kfsNum - 1 : frameIdx + 2][valueKey];
- if (arrDim > 0) {
- arrDim === 1
- ? catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w)
- : catmullRomInterpolate2DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w);
- }
- else if (isValueColor) {
- catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w);
- if (!isAdditive) {
- target[propName] = rgba2String(targetArr);
- }
- }
- else {
- var value = void 0;
- if (!this.interpolable) {
- value = p2;
- }
- else {
- value = catmullRomInterpolate(p0, p1, p2, p3, w, w * w, w * w * w);
- }
- if (isAdditive) {
- this._additiveValue = value;
- }
- else {
- target[propName] = value;
- }
- }
- }
- else {
- if (arrDim > 0) {
- arrDim === 1
- ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w)
- : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
- }
- else if (isValueColor) {
- interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
- if (!isAdditive) {
- target[propName] = rgba2String(targetArr);
- }
- }
- else {
- var value = void 0;
- if (!this.interpolable) {
- value = step(frame[valueKey], nextFrame[valueKey], w);
- }
- else {
- value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w);
- }
- if (isAdditive) {
- this._additiveValue = value;
- }
- else {
- target[propName] = value;
- }
- }
- }
- if (isAdditive) {
- this._addToTarget(target);
- }
- };
- Track.prototype._addToTarget = function (target) {
- var arrDim = this.arrDim;
- var propName = this.propName;
- var additiveValue = this._additiveValue;
- if (arrDim === 0) {
- if (this.isValueColor) {
- color.parse(target[propName], tmpRgba);
- add1DArray(tmpRgba, tmpRgba, additiveValue, 1);
- target[propName] = rgba2String(tmpRgba);
- }
- else {
- target[propName] = target[propName] + additiveValue;
- }
- }
- else if (arrDim === 1) {
- add1DArray(target[propName], target[propName], additiveValue, 1);
- }
- else if (arrDim === 2) {
- add2DArray(target[propName], target[propName], additiveValue, 1);
- }
- };
- return Track;
- }());
- var Animator = (function () {
- function Animator(target, loop, additiveTo) {
- this._tracks = {};
- this._trackKeys = [];
- this._delay = 0;
- this._maxTime = 0;
- this._paused = false;
- this._started = 0;
- this._clip = null;
- this._target = target;
- this._loop = loop;
- if (loop && additiveTo) {
- logError('Can\' use additive animation on looped animation.');
- return;
- }
- this._additiveAnimators = additiveTo;
- }
- Animator.prototype.getTarget = function () {
- return this._target;
- };
- Animator.prototype.changeTarget = function (target) {
- this._target = target;
- };
- Animator.prototype.when = function (time, props) {
- return this.whenWithKeys(time, props, keys(props));
- };
- Animator.prototype.whenWithKeys = function (time, props, propNames) {
- var tracks = this._tracks;
- for (var i = 0; i < propNames.length; i++) {
- var propName = propNames[i];
- var track = tracks[propName];
- if (!track) {
- track = tracks[propName] = new Track(propName);
- var initialValue = void 0;
- var additiveTrack = this._getAdditiveTrack(propName);
- if (additiveTrack) {
- var lastFinalKf = additiveTrack.keyframes[additiveTrack.keyframes.length - 1];
- initialValue = lastFinalKf && lastFinalKf.value;
- if (additiveTrack.isValueColor && initialValue) {
- initialValue = rgba2String(initialValue);
- }
- }
- else {
- initialValue = this._target[propName];
- }
- if (initialValue == null) {
- continue;
- }
- if (time !== 0) {
- track.addKeyframe(0, cloneValue(initialValue));
- }
- this._trackKeys.push(propName);
- }
- track.addKeyframe(time, cloneValue(props[propName]));
- }
- this._maxTime = Math.max(this._maxTime, time);
- return this;
- };
- Animator.prototype.pause = function () {
- this._clip.pause();
- this._paused = true;
- };
- Animator.prototype.resume = function () {
- this._clip.resume();
- this._paused = false;
- };
- Animator.prototype.isPaused = function () {
- return !!this._paused;
- };
- Animator.prototype._doneCallback = function () {
- this._setTracksFinished();
- this._clip = null;
- var doneList = this._doneCbs;
- if (doneList) {
- var len = doneList.length;
- for (var i = 0; i < len; i++) {
- doneList[i].call(this);
- }
- }
- };
- Animator.prototype._abortedCallback = function () {
- this._setTracksFinished();
- var animation = this.animation;
- var abortedList = this._abortedCbs;
- if (animation) {
- animation.removeClip(this._clip);
- }
- this._clip = null;
- if (abortedList) {
- for (var i = 0; i < abortedList.length; i++) {
- abortedList[i].call(this);
- }
- }
- };
- Animator.prototype._setTracksFinished = function () {
- var tracks = this._tracks;
- var tracksKeys = this._trackKeys;
- for (var i = 0; i < tracksKeys.length; i++) {
- tracks[tracksKeys[i]].setFinished();
- }
- };
- Animator.prototype._getAdditiveTrack = function (trackName) {
- var additiveTrack;
- var additiveAnimators = this._additiveAnimators;
- if (additiveAnimators) {
- for (var i = 0; i < additiveAnimators.length; i++) {
- var track = additiveAnimators[i].getTrack(trackName);
- if (track) {
- additiveTrack = track;
- }
- }
- }
- return additiveTrack;
- };
- Animator.prototype.start = function (easing, forceAnimate) {
- if (this._started > 0) {
- return;
- }
- this._started = 1;
- var self = this;
- var tracks = [];
- for (var i = 0; i < this._trackKeys.length; i++) {
- var propName = this._trackKeys[i];
- var track = this._tracks[propName];
- var additiveTrack = this._getAdditiveTrack(propName);
- var kfs = track.keyframes;
- track.prepare(additiveTrack);
- if (track.needsAnimate()) {
- tracks.push(track);
- }
- else if (!track.interpolable) {
- var lastKf = kfs[kfs.length - 1];
- if (lastKf) {
- self._target[track.propName] = lastKf.value;
- }
- }
- }
- if (tracks.length || forceAnimate) {
- var clip = new Clip({
- life: this._maxTime,
- loop: this._loop,
- delay: this._delay,
- onframe: function (percent) {
- self._started = 2;
- var additiveAnimators = self._additiveAnimators;
- if (additiveAnimators) {
- var stillHasAdditiveAnimator = false;
- for (var i = 0; i < additiveAnimators.length; i++) {
- if (additiveAnimators[i]._clip) {
- stillHasAdditiveAnimator = true;
- break;
- }
- }
- if (!stillHasAdditiveAnimator) {
- self._additiveAnimators = null;
- }
- }
- for (var i = 0; i < tracks.length; i++) {
- tracks[i].step(self._target, percent);
- }
- var onframeList = self._onframeCbs;
- if (onframeList) {
- for (var i = 0; i < onframeList.length; i++) {
- onframeList[i](self._target, percent);
- }
- }
- },
- ondestroy: function () {
- self._doneCallback();
- }
- });
- this._clip = clip;
- if (this.animation) {
- this.animation.addClip(clip);
- }
- if (easing && easing !== 'spline') {
- clip.easing = easing;
- }
- }
- else {
- this._doneCallback();
- }
- return this;
- };
- Animator.prototype.stop = function (forwardToLast) {
- if (!this._clip) {
- return;
- }
- var clip = this._clip;
- if (forwardToLast) {
- clip.onframe(1);
- }
- this._abortedCallback();
- };
- Animator.prototype.delay = function (time) {
- this._delay = time;
- return this;
- };
- Animator.prototype.during = function (cb) {
- if (cb) {
- if (!this._onframeCbs) {
- this._onframeCbs = [];
- }
- this._onframeCbs.push(cb);
- }
- return this;
- };
- Animator.prototype.done = function (cb) {
- if (cb) {
- if (!this._doneCbs) {
- this._doneCbs = [];
- }
- this._doneCbs.push(cb);
- }
- return this;
- };
- Animator.prototype.aborted = function (cb) {
- if (cb) {
- if (!this._abortedCbs) {
- this._abortedCbs = [];
- }
- this._abortedCbs.push(cb);
- }
- return this;
- };
- Animator.prototype.getClip = function () {
- return this._clip;
- };
- Animator.prototype.getTrack = function (propName) {
- return this._tracks[propName];
- };
- Animator.prototype.stopTracks = function (propNames, forwardToLast) {
- if (!propNames.length || !this._clip) {
- return true;
- }
- var tracks = this._tracks;
- var tracksKeys = this._trackKeys;
- for (var i = 0; i < propNames.length; i++) {
- var track = tracks[propNames[i]];
- if (track) {
- if (forwardToLast) {
- track.step(this._target, 1);
- }
- else if (this._started === 1) {
- track.step(this._target, 0);
- }
- track.setFinished();
- }
- }
- var allAborted = true;
- for (var i = 0; i < tracksKeys.length; i++) {
- if (!tracks[tracksKeys[i]].isFinished()) {
- allAborted = false;
- break;
- }
- }
- if (allAborted) {
- this._abortedCallback();
- }
- return allAborted;
- };
- Animator.prototype.saveFinalToTarget = function (target, trackKeys) {
- if (!target) {
- return;
- }
- trackKeys = trackKeys || this._trackKeys;
- for (var i = 0; i < trackKeys.length; i++) {
- var propName = trackKeys[i];
- var track = this._tracks[propName];
- if (!track || track.isFinished()) {
- continue;
- }
- var kfs = track.keyframes;
- var lastKf = kfs[kfs.length - 1];
- if (lastKf) {
- var val = cloneValue(lastKf.value);
- if (track.isValueColor) {
- val = rgba2String(val);
- }
- target[propName] = val;
- }
- }
- };
- Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) {
- trackKeys = trackKeys || keys(finalProps);
- for (var i = 0; i < trackKeys.length; i++) {
- var propName = trackKeys[i];
- var track = this._tracks[propName];
- if (!track) {
- continue;
- }
- var kfs = track.keyframes;
- if (kfs.length > 1) {
- var lastKf = kfs.pop();
- track.addKeyframe(lastKf.time, finalProps[propName]);
- track.prepare(track.getAdditiveTrack());
- }
- }
- };
- return Animator;
- }());
- export default Animator;
|