blob: 2cbf3d2a649b030c7680d79f34eace22cd4d54d5 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
import type { CanvasRenderer } from "../canvas-renderer";
import { BaseNode } from "./base-node";
import type { TextElement } from "@/types/timeline";
export type TextNodeParams = TextElement & {
canvasCenter: { x: number; y: number };
textBaseline?: CanvasTextBaseline;
};
export class TextNode extends BaseNode<TextNodeParams> {
isInRange({ time }: { time: number }) {
return (
time >= this.params.startTime &&
time < this.params.startTime + this.params.duration
);
}
async render({ renderer, time }: { renderer: CanvasRenderer; time: number }) {
if (!this.isInRange({ time })) {
return;
}
renderer.context.save();
const x = this.params.transform.position.x + this.params.canvasCenter.x;
const y = this.params.transform.position.y + this.params.canvasCenter.y;
renderer.context.translate(x, y);
if (this.params.transform.rotate) {
renderer.context.rotate((this.params.transform.rotate * Math.PI) / 180);
}
const fontWeight = this.params.fontWeight === "bold" ? "bold" : "normal";
const fontStyle = this.params.fontStyle === "italic" ? "italic" : "normal";
renderer.context.font = `${fontStyle} ${fontWeight} ${this.params.fontSize}px ${this.params.fontFamily}`;
renderer.context.textAlign = this.params.textAlign;
renderer.context.textBaseline = this.params.textBaseline || "middle";
renderer.context.fillStyle = this.params.color;
const prevAlpha = renderer.context.globalAlpha;
renderer.context.globalAlpha = this.params.opacity;
if (this.params.backgroundColor) {
const metrics = renderer.context.measureText(this.params.content);
const ascent =
metrics.actualBoundingBoxAscent ?? this.params.fontSize * 0.8;
const descent =
metrics.actualBoundingBoxDescent ?? this.params.fontSize * 0.2;
const textW = metrics.width;
const textH = ascent + descent;
const padX = 8;
const padY = 4;
renderer.context.fillStyle = this.params.backgroundColor;
let bgLeft = -textW / 2;
if (renderer.context.textAlign === "left") bgLeft = 0;
if (renderer.context.textAlign === "right") bgLeft = -textW;
renderer.context.fillRect(
bgLeft - padX,
-textH / 2 - padY,
textW + padX * 2,
textH + padY * 2,
);
renderer.context.fillStyle = this.params.color;
}
renderer.context.fillText(this.params.content, 0, 0);
renderer.context.globalAlpha = prevAlpha;
renderer.context.restore();
}
}
|