-
Notifications
You must be signed in to change notification settings - Fork 2
/
node.ts
91 lines (67 loc) · 2.18 KB
/
node.ts
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// A drawable node for Motion scenes.
import { point, type Point, type PointLike } from "./point.js"
import { signal, untrack, type Signal, type SignalLike } from "./signal.js"
export interface NodeProps {
x?: SignalLike<number>
y?: SignalLike<number>
fill?: SignalLike<string>
fillRule?: SignalLike<CanvasFillRule>
origin?: SignalLike<PointLike>
translate?: SignalLike<PointLike>
stroke?: SignalLike<string>
strokeWidth?: SignalLike<number>
scale?: SignalLike<number>
children?: Node[]
}
export abstract class Node {
readonly x: Signal<number>
readonly y: Signal<number>
readonly origin: Signal<Point>
readonly translate: Signal<Point>
readonly stroke: Signal<string>
readonly strokeWidth: Signal<number>
readonly fill: Signal<string>
readonly fillRule: Signal<CanvasFillRule | undefined>
readonly scale: Signal<number>
readonly children: Node[]
constructor(props: NodeProps) {
this.children = props.children || []
this.x = signal(props.x || 0)
this.y = signal(props.y || 0)
this.origin = point(props.origin || 0)
this.translate = point(props.translate || 0)
this.stroke = signal(props.stroke || "transparent")
this.strokeWidth = signal(props.strokeWidth || 0)
this.fill = signal(props.fill || "transparent")
this.fillRule = signal(props.fillRule)
this.scale = signal(props.scale ?? 1)
}
abstract draw(path: Path2D): void
render(context: CanvasRenderingContext2D) {
context.save()
context.translate(this.origin().x, this.origin().y)
context.scale(this.scale(), this.scale())
context.translate(-this.origin().x, -this.origin().y)
context.translate(this.translate().x, this.translate().y)
const path = new Path2D()
this.draw(path)
{
const fill = untrack(this.fill)
if (fill && fill != "transparent") {
context.fillStyle = fill
context.fill(path, untrack(this.fillRule))
}
}
{
const stroke = untrack(this.stroke)
if (stroke && stroke != "transparent") {
context.strokeStyle = stroke
context.stroke(path)
}
}
for (const child of this.children) {
child.render(context)
}
context.restore()
}
}