light-chart
Version:
Charts for mobile visualization.
115 lines (99 loc) • 2.84 kB
JavaScript
const { requestAnimationFrame } = require('../util/requestAnimationFrame');
const clock = typeof performance === 'object' && performance.now ? performance : Date;
class Timeline {
constructor() {
this.anims = [];
this.time = null;
this.playing = false;
this.canvas = [];
}
play() {
const self = this;
self.time = clock.now();
self.playing = true;
function step() {
if (self.playing) {
requestAnimationFrame(step);
self.update();
}
}
requestAnimationFrame(step);
}
stop() {
this.playing = false;
this.time = null;
this.canvas = [];
}
update() {
const currentTime = clock.now();
this.canvas = [];
for (let i = 0; i < this.anims.length; i++) {
const propertyAnim = this.anims[i];
if (currentTime < propertyAnim.startTime || propertyAnim.hasEnded) {
continue;
}
const shape = propertyAnim.shape; // shape
if (shape.get('destroyed')) {
this.anims.splice(i, 1);
i--;
continue;
}
const { startState, endState, interpolate, duration } = propertyAnim;
if (currentTime >= propertyAnim.startTime && !propertyAnim.hasStarted) {
propertyAnim.hasStarted = true;
if (propertyAnim.onStart) {
propertyAnim.onStart();
}
}
let t = (currentTime - propertyAnim.startTime) / duration;
t = Math.max(0, Math.min(t, 1));
t = propertyAnim.easing(t);
if (propertyAnim.onFrame) {
propertyAnim.onFrame(t);
} else {
for (const key in interpolate) {
const diff = interpolate[key];
const value = diff(t);
let newValue;
if (key === 'points') {
newValue = [];
const aLen = Math.max(startState.points.length, endState.points.length);
for (let j = 0; j < aLen; j += 2) {
newValue.push({
x: value[j],
y: value[j + 1]
});
}
} else {
newValue = value;
}
shape._attrs.attrs[key] = newValue;
shape._attrs.bbox = null; // should clear calculated bbox
}
}
const canvas = shape.get('canvas');
if (this.canvas.indexOf(canvas) === -1) {
this.canvas.push(canvas);
}
if (propertyAnim.onUpdate) {
propertyAnim.onUpdate(t);
}
if (currentTime >= propertyAnim.endTime && !propertyAnim.hasEnded) {
propertyAnim.hasEnded = true;
if (propertyAnim.onEnd) {
propertyAnim.onEnd();
}
}
if (t === 1) { // end
this.anims.splice(i, 1);
i--;
}
}
this.canvas.map(c => {
c.draw();
return c;
});
this.time = clock.now();
}
}
module.exports = Timeline;