konva
Version:
HTML5 2d canvas library.
525 lines (524 loc) • 15.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Easings = exports.Tween = void 0;
const Util_1 = require("./Util");
const Animation_1 = require("./Animation");
const Node_1 = require("./Node");
const Global_1 = require("./Global");
const blacklist = {
node: 1,
duration: 1,
easing: 1,
onFinish: 1,
yoyo: 1,
}, PAUSED = 1, PLAYING = 2, REVERSING = 3, colorAttrs = ['fill', 'stroke', 'shadowColor'];
let idCounter = 0;
class TweenEngine {
constructor(prop, propFunc, func, begin, finish, duration, yoyo) {
this.prop = prop;
this.propFunc = propFunc;
this.begin = begin;
this._pos = begin;
this.duration = duration;
this._change = 0;
this.prevPos = 0;
this.yoyo = yoyo;
this._time = 0;
this._position = 0;
this._startTime = 0;
this._finish = 0;
this.func = func;
this._change = finish - this.begin;
this.pause();
}
fire(str) {
const handler = this[str];
if (handler) {
handler();
}
}
setTime(t) {
if (t > this.duration) {
if (this.yoyo) {
this._time = this.duration;
this.reverse();
}
else {
this.finish();
}
}
else if (t < 0) {
if (this.yoyo) {
this._time = 0;
this.play();
}
else {
this.reset();
}
}
else {
this._time = t;
this.update();
}
}
getTime() {
return this._time;
}
setPosition(p) {
this.prevPos = this._pos;
this.propFunc(p);
this._pos = p;
}
getPosition(t) {
if (t === undefined) {
t = this._time;
}
return this.func(t, this.begin, this._change, this.duration);
}
play() {
this.state = PLAYING;
this._startTime = this.getTimer() - this._time;
this.onEnterFrame();
this.fire('onPlay');
}
reverse() {
this.state = REVERSING;
this._time = this.duration - this._time;
this._startTime = this.getTimer() - this._time;
this.onEnterFrame();
this.fire('onReverse');
}
seek(t) {
this.pause();
this._time = t;
this.update();
this.fire('onSeek');
}
reset() {
this.pause();
this._time = 0;
this.update();
this.fire('onReset');
}
finish() {
this.pause();
this._time = this.duration;
this.update();
this.fire('onFinish');
}
update() {
this.setPosition(this.getPosition(this._time));
this.fire('onUpdate');
}
onEnterFrame() {
const t = this.getTimer() - this._startTime;
if (this.state === PLAYING) {
this.setTime(t);
}
else if (this.state === REVERSING) {
this.setTime(this.duration - t);
}
}
pause() {
this.state = PAUSED;
this.fire('onPause');
}
getTimer() {
return new Date().getTime();
}
}
class Tween {
constructor(config) {
const that = this, node = config.node, nodeId = node._id, easing = config.easing || exports.Easings.Linear, yoyo = !!config.yoyo;
let duration, key;
if (typeof config.duration === 'undefined') {
duration = 0.3;
}
else if (config.duration === 0) {
duration = 0.001;
}
else {
duration = config.duration;
}
this.node = node;
this._id = idCounter++;
const layers = node.getLayer() ||
(node instanceof Global_1.Konva['Stage'] ? node.getLayers() : null);
if (!layers) {
Util_1.Util.error('Tween constructor have `node` that is not in a layer. Please add node into layer first.');
}
this.anim = new Animation_1.Animation(function () {
that.tween.onEnterFrame();
}, layers);
this.tween = new TweenEngine(key, function (i) {
that._tweenFunc(i);
}, easing, 0, 1, duration * 1000, yoyo);
this._addListeners();
if (!Tween.attrs[nodeId]) {
Tween.attrs[nodeId] = {};
}
if (!Tween.attrs[nodeId][this._id]) {
Tween.attrs[nodeId][this._id] = {};
}
if (!Tween.tweens[nodeId]) {
Tween.tweens[nodeId] = {};
}
for (key in config) {
if (blacklist[key] === undefined) {
this._addAttr(key, config[key]);
}
}
this.reset();
this.onFinish = config.onFinish;
this.onReset = config.onReset;
this.onUpdate = config.onUpdate;
}
_addAttr(key, end) {
const node = this.node, nodeId = node._id;
let diff, len, trueEnd, trueStart, endRGBA;
const tweenId = Tween.tweens[nodeId][key];
if (tweenId) {
delete Tween.attrs[nodeId][tweenId][key];
}
let start = node.getAttr(key);
if (Util_1.Util._isArray(end)) {
diff = [];
len = Math.max(end.length, start.length);
if (key === 'points' && end.length !== start.length) {
if (end.length > start.length) {
trueStart = start;
start = Util_1.Util._prepareArrayForTween(start, end, node.closed());
}
else {
trueEnd = end;
end = Util_1.Util._prepareArrayForTween(end, start, node.closed());
}
}
if (key.indexOf('fill') === 0) {
for (let n = 0; n < len; n++) {
if (n % 2 === 0) {
diff.push(end[n] - start[n]);
}
else {
const startRGBA = Util_1.Util.colorToRGBA(start[n]);
endRGBA = Util_1.Util.colorToRGBA(end[n]);
start[n] = startRGBA;
diff.push({
r: endRGBA.r - startRGBA.r,
g: endRGBA.g - startRGBA.g,
b: endRGBA.b - startRGBA.b,
a: endRGBA.a - startRGBA.a,
});
}
}
}
else {
for (let n = 0; n < len; n++) {
diff.push(end[n] - start[n]);
}
}
}
else if (colorAttrs.indexOf(key) !== -1) {
start = Util_1.Util.colorToRGBA(start);
endRGBA = Util_1.Util.colorToRGBA(end);
diff = {
r: endRGBA.r - start.r,
g: endRGBA.g - start.g,
b: endRGBA.b - start.b,
a: endRGBA.a - start.a,
};
}
else {
diff = end - start;
}
Tween.attrs[nodeId][this._id][key] = {
start: start,
diff: diff,
end: end,
trueEnd: trueEnd,
trueStart: trueStart,
};
Tween.tweens[nodeId][key] = this._id;
}
_tweenFunc(i) {
const node = this.node, attrs = Tween.attrs[node._id][this._id];
let key, attr, start, diff, newVal, n, len, end;
for (key in attrs) {
attr = attrs[key];
start = attr.start;
diff = attr.diff;
end = attr.end;
if (Util_1.Util._isArray(start)) {
newVal = [];
len = Math.max(start.length, end.length);
if (key.indexOf('fill') === 0) {
for (n = 0; n < len; n++) {
if (n % 2 === 0) {
newVal.push((start[n] || 0) + diff[n] * i);
}
else {
newVal.push('rgba(' +
Math.round(start[n].r + diff[n].r * i) +
',' +
Math.round(start[n].g + diff[n].g * i) +
',' +
Math.round(start[n].b + diff[n].b * i) +
',' +
(start[n].a + diff[n].a * i) +
')');
}
}
}
else {
for (n = 0; n < len; n++) {
newVal.push((start[n] || 0) + diff[n] * i);
}
}
}
else if (colorAttrs.indexOf(key) !== -1) {
newVal =
'rgba(' +
Math.round(start.r + diff.r * i) +
',' +
Math.round(start.g + diff.g * i) +
',' +
Math.round(start.b + diff.b * i) +
',' +
(start.a + diff.a * i) +
')';
}
else {
newVal = start + diff * i;
}
node.setAttr(key, newVal);
}
}
_addListeners() {
this.tween.onPlay = () => {
this.anim.start();
};
this.tween.onReverse = () => {
this.anim.start();
};
this.tween.onPause = () => {
this.anim.stop();
};
this.tween.onFinish = () => {
const node = this.node;
const attrs = Tween.attrs[node._id][this._id];
if (attrs.points && attrs.points.trueEnd) {
node.setAttr('points', attrs.points.trueEnd);
}
if (this.onFinish) {
this.onFinish.call(this);
}
};
this.tween.onReset = () => {
const node = this.node;
const attrs = Tween.attrs[node._id][this._id];
if (attrs.points && attrs.points.trueStart) {
node.points(attrs.points.trueStart);
}
if (this.onReset) {
this.onReset();
}
};
this.tween.onUpdate = () => {
if (this.onUpdate) {
this.onUpdate.call(this);
}
};
}
play() {
this.tween.play();
return this;
}
reverse() {
this.tween.reverse();
return this;
}
reset() {
this.tween.reset();
return this;
}
seek(t) {
this.tween.seek(t * 1000);
return this;
}
pause() {
this.tween.pause();
return this;
}
finish() {
this.tween.finish();
return this;
}
destroy() {
const nodeId = this.node._id, thisId = this._id, attrs = Tween.tweens[nodeId];
this.pause();
for (const key in attrs) {
delete Tween.tweens[nodeId][key];
}
delete Tween.attrs[nodeId][thisId];
}
}
exports.Tween = Tween;
Tween.attrs = {};
Tween.tweens = {};
Node_1.Node.prototype.to = function (params) {
const onFinish = params.onFinish;
params.node = this;
params.onFinish = function () {
this.destroy();
if (onFinish) {
onFinish();
}
};
const tween = new Tween(params);
tween.play();
};
exports.Easings = {
BackEaseIn(t, b, c, d) {
const s = 1.70158;
return c * (t /= d) * t * ((s + 1) * t - s) + b;
},
BackEaseOut(t, b, c, d) {
const s = 1.70158;
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
},
BackEaseInOut(t, b, c, d) {
let s = 1.70158;
if ((t /= d / 2) < 1) {
return (c / 2) * (t * t * (((s *= 1.525) + 1) * t - s)) + b;
}
return (c / 2) * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b;
},
ElasticEaseIn(t, b, c, d, a, p) {
let s = 0;
if (t === 0) {
return b;
}
if ((t /= d) === 1) {
return b + c;
}
if (!p) {
p = d * 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = (p / (2 * Math.PI)) * Math.asin(c / a);
}
return (-(a *
Math.pow(2, 10 * (t -= 1)) *
Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b);
},
ElasticEaseOut(t, b, c, d, a, p) {
let s = 0;
if (t === 0) {
return b;
}
if ((t /= d) === 1) {
return b + c;
}
if (!p) {
p = d * 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = (p / (2 * Math.PI)) * Math.asin(c / a);
}
return (a * Math.pow(2, -10 * t) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) +
c +
b);
},
ElasticEaseInOut(t, b, c, d, a, p) {
let s = 0;
if (t === 0) {
return b;
}
if ((t /= d / 2) === 2) {
return b + c;
}
if (!p) {
p = d * (0.3 * 1.5);
}
if (!a || a < Math.abs(c)) {
a = c;
s = p / 4;
}
else {
s = (p / (2 * Math.PI)) * Math.asin(c / a);
}
if (t < 1) {
return (-0.5 *
(a *
Math.pow(2, 10 * (t -= 1)) *
Math.sin(((t * d - s) * (2 * Math.PI)) / p)) +
b);
}
return (a *
Math.pow(2, -10 * (t -= 1)) *
Math.sin(((t * d - s) * (2 * Math.PI)) / p) *
0.5 +
c +
b);
},
BounceEaseOut(t, b, c, d) {
if ((t /= d) < 1 / 2.75) {
return c * (7.5625 * t * t) + b;
}
else if (t < 2 / 2.75) {
return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;
}
else if (t < 2.5 / 2.75) {
return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;
}
else {
return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;
}
},
BounceEaseIn(t, b, c, d) {
return c - exports.Easings.BounceEaseOut(d - t, 0, c, d) + b;
},
BounceEaseInOut(t, b, c, d) {
if (t < d / 2) {
return exports.Easings.BounceEaseIn(t * 2, 0, c, d) * 0.5 + b;
}
else {
return exports.Easings.BounceEaseOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
}
},
EaseIn(t, b, c, d) {
return c * (t /= d) * t + b;
},
EaseOut(t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
},
EaseInOut(t, b, c, d) {
if ((t /= d / 2) < 1) {
return (c / 2) * t * t + b;
}
return (-c / 2) * (--t * (t - 2) - 1) + b;
},
StrongEaseIn(t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
},
StrongEaseOut(t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
StrongEaseInOut(t, b, c, d) {
if ((t /= d / 2) < 1) {
return (c / 2) * t * t * t * t * t + b;
}
return (c / 2) * ((t -= 2) * t * t * t * t + 2) + b;
},
Linear(t, b, c, d) {
return (c * t) / d + b;
},
};