Skip to content

Commit

Permalink
feat(statistic): abstracted common code from the statistic component (#…
Browse files Browse the repository at this point in the history
…1644)

* feat(statistic): abstracted common code from the statistic component

* chore: add polyfill and fix elapsed

* chore: fix lint

---------

Co-authored-by: wū yāng <[email protected]>
  • Loading branch information
oljc and uyarn authored Nov 16, 2023
1 parent 8d6eae0 commit 0eb8a24
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
144 changes: 144 additions & 0 deletions js/statistic/tween.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* Inspired by https://github.com/PengJiyuan/b-tween
* requestAnimationFrame https://caniuse.com/requestanimationframe
* TDesign vue 2 need to ensure compatibility with users who are using IE and Vue2,
* it is necessary to use setInterval instead of requestAnimationFrame when the browser version is less than 9
*/
import { getIEVersion } from '../utils/helper';

export interface TweenSettings {
from: Record<string, number>;
to: Record<string, number>;
duration?: number;
delay?: number;
onStart?: (keys: Record<string, number>) => void;
onUpdate?: (keys: Record<string, number>) => void;
onFinish?: (keys: Record<string, number>) => void;
}

const quartOut = (t: number) => 1 - Math.abs((t - 1) ** 4);

export default class Tween {
private from: Record<string, number>;

private to: Record<string, number>;

private duration: number;

private onStart?: (keys: Record<string, number>) => void;

private onUpdate: (keys: Record<string, number>) => void;

private onFinish?: (keys: Record<string, number>) => void;

private startTime: number;

private started: boolean;

private finished: boolean;

private timer: number | NodeJS.Timer | null;

private keys: Record<string, number>;

constructor({
from,
to,
duration = 200,
onStart,
onUpdate = () => {},
onFinish,
}: TweenSettings) {
this.from = from;
this.to = to;
this.duration = duration;
this.onStart = onStart;
this.onUpdate = onUpdate;
this.onFinish = onFinish;
this.startTime = Date.now();
this.started = false;
this.finished = false;
this.timer = null;
this.keys = {};
Object.entries(from).forEach(([key, value]) => {
if (this.to[key] === undefined) {
this.to[key] = value;
}
});

Object.entries(to).forEach(([key, value]) => {
if (this.from[key] === undefined) {
this.from[key] = value;
}
});
}

private time = 0;

private elapsed = 0;

private update() {
this.time = Date.now();
if (this.time < this.startTime || this.finished) return;

if (this.elapsed >= this.duration) {
this.finished = true;
this.onFinish?.(this.keys);
return;
}
const elapsed = Math.min(this.time - this.startTime, this.duration);
this.elapsed = elapsed;
const progress = quartOut(elapsed / this.duration);

Object.keys(this.to).forEach((key) => {
const delta = this.to[key] - this.from[key];
this.keys[key] = this.from[key] + delta * progress;
});

if (!this.started) {
this.onStart?.(this.keys);
this.started = true;
}

this.onUpdate(this.keys);
}

private polyfillStart() {
const elapsed = Date.now() - this.startTime;
const interval = quartOut(elapsed / this.duration);

this.timer = setInterval(() => {
this.update();
if (this.finished) {
clearInterval(this.timer as number);
}
}, interval);
}

private normalStart() {
const tick = () => {
this.update();
this.timer = requestAnimationFrame(tick);

if (this.finished) {
cancelAnimationFrame(this.timer);
this.timer = null;
}
};
tick();
}

public start() {
this.startTime = Date.now();
// IE < 10
if (getIEVersion() > 10) this.polyfillStart();
else this.normalStart();
}

public stop() {
// IE < 10
if (getIEVersion() > 10) clearInterval(this.timer as number);
else cancelAnimationFrame(this.timer as number);
this.timer = null;
}
}
9 changes: 9 additions & 0 deletions js/statistic/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* 颜色映射
*/
export const COLOR_MAP = {
blue: 'var(--td-brand-color)',
red: 'var(--td-error-color)',
orange: 'var(--td-warning-color)',
green: 'var(--td-success-color)',
};

0 comments on commit 0eb8a24

Please sign in to comment.