mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-03 01:54:58 +08:00
feat: 文字弹出
This commit is contained in:
1 parent
597333adf7
commit
ae5a8f6363
2 files changed
+101
No files matched your search
@@ -0,0 +1,96 @@
|
||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
||||
import { RenderItem, RenderItemPosition } from '@/core/render/item';
|
||||
import { Transform } from '@/core/render/transform';
|
||||
import { TimingFn } from 'mutate-animate';
|
||||
|
||||
interface PopData {
|
||||
cx: number;
|
||||
cy: number;
|
||||
path: TimingFn<2>;
|
||||
text: string;
|
||||
time: number;
|
||||
start: number;
|
||||
color: CanvasStyle;
|
||||
}
|
||||
|
||||
function parabola(input: number): [number, number] {
|
||||
const x = input * 100;
|
||||
return [x, x ** 2 / 20 - 3 * x];
|
||||
}
|
||||
|
||||
export class PopText extends RenderItem {
|
||||
private popList: Set<PopData> = new Set();
|
||||
|
||||
private delegation: number = 0;
|
||||
|
||||
constructor(type: RenderItemPosition) {
|
||||
super(type, false);
|
||||
this.delegation = this.delegateTicker(() => {
|
||||
if (this.popList.size > 0) this.update();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个弹出文字
|
||||
* @param text 要显示的文字
|
||||
* @param time 持续时长
|
||||
* @param cx 中心点,也就是从哪弹出的
|
||||
* @param cy 中心点,也就是从哪弹出的
|
||||
* @param path 自定义路径,不填表示默认的抛物线路径
|
||||
*/
|
||||
addPop(
|
||||
text: string,
|
||||
time: number,
|
||||
cx: number,
|
||||
cy: number,
|
||||
color: CanvasStyle,
|
||||
path?: TimingFn<2>
|
||||
) {
|
||||
this.popList.add({
|
||||
text,
|
||||
time,
|
||||
cx,
|
||||
cy,
|
||||
color,
|
||||
path: path ?? parabola,
|
||||
start: Date.now()
|
||||
});
|
||||
this.update();
|
||||
}
|
||||
|
||||
protected render(
|
||||
canvas: MotaOffscreenCanvas2D,
|
||||
transform: Transform
|
||||
): void {
|
||||
const ctx = canvas.ctx;
|
||||
const toDelete = new Set<PopData>();
|
||||
const now = Date.now();
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.font = '22px Verdana';
|
||||
ctx.lineWidth = 3;
|
||||
this.popList.forEach(v => {
|
||||
const { cx, cy, path, text, color, time, start } = v;
|
||||
const dt = now - start;
|
||||
const progress = dt / time;
|
||||
if (progress >= 1) {
|
||||
toDelete.add(v);
|
||||
return;
|
||||
}
|
||||
const [x, y] = path(progress);
|
||||
const dx = cx + x;
|
||||
const dy = cy + y;
|
||||
ctx.globalAlpha = Math.min(1, 2 - progress * 2);
|
||||
ctx.fillStyle = color;
|
||||
ctx.strokeText(text, dx, dy);
|
||||
ctx.fillText(text, dx, dy);
|
||||
});
|
||||
toDelete.forEach(v => {
|
||||
this.popList.delete(v);
|
||||
});
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
super.destroy();
|
||||
this.removeTicker(this.delegation);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user