This commit is contained in:
th committed 2026-04-19 17:53:36 +02:00
commit c6863f2bfc
34 files changed
+6909

No files matched your search

+86
View File
@@ -0,0 +1,86 @@
import type { Asset, Scene } from '@/types/scene'
import { sampleLayer } from './interpolate'
export async function loadSceneImages(scene: Scene): Promise<Record<string, HTMLImageElement>> {
const result: Record<string, HTMLImageElement> = {}
const images = scene.assets.filter(
(a): a is Extract<Asset, { kind: 'image' }> => a.kind === 'image',
)
await Promise.all(
images.map(
(a) =>
new Promise<void>((resolve) => {
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {
result[a.id] = img
resolve()
}
img.onerror = () => resolve()
img.src = a.src
}),
),
)
return result
}
export function drawSceneFrame(
ctx: CanvasRenderingContext2D,
scene: Scene,
time: number,
images: Record<string, HTMLImageElement>,
) {
const lw = scene.canvas.width
const lh = scene.canvas.height
ctx.save()
ctx.beginPath()
ctx.rect(0, 0, lw, lh)
ctx.clip()
ctx.fillStyle = scene.canvas.background
ctx.fillRect(0, 0, lw, lh)
const assetMap = new Map<string, Asset>()
for (const a of scene.assets) assetMap.set(a.id, a)
for (const layer of scene.layers) {
if (!layer.visible) continue
const asset = assetMap.get(layer.assetId)
if (!asset) continue
const p = sampleLayer(layer, time)
ctx.save()
ctx.globalAlpha *= p.opacity
ctx.translate(p.x, p.y)
ctx.rotate((p.rotation * Math.PI) / 180)
ctx.scale(p.scaleX, p.scaleY)
if (asset.kind === 'rect') {
const offX = layer.offsetX ?? asset.width / 2
const offY = layer.offsetY ?? asset.height / 2
ctx.fillStyle = p.fill ?? asset.fill
ctx.fillRect(-offX, -offY, asset.width, asset.height)
} else if (asset.kind === 'circle') {
ctx.fillStyle = p.fill ?? asset.fill
ctx.beginPath()
ctx.arc(0, 0, asset.radius, 0, Math.PI * 2)
ctx.fill()
} else if (asset.kind === 'text') {
ctx.fillStyle = p.fill ?? asset.fill
ctx.font = `${asset.fontSize}px sans-serif`
ctx.textBaseline = 'top'
ctx.fillText(asset.text, 0, 0)
} else if (asset.kind === 'image') {
const img = images[asset.id]
if (img) {
const offX = layer.offsetX ?? asset.width / 2
const offY = layer.offsetY ?? asset.height / 2
ctx.drawImage(img, -offX, -offY, asset.width, asset.height)
}
}
ctx.restore()
}
ctx.restore()
}