bak
This commit is contained in:
1 parent
6b6157d786
commit
3ef5fb5a2d
19 files changed
+1244
-94
No files matched your search
+71
-3
@@ -1,4 +1,4 @@
|
||||
import type { Asset, Layer, Scene } from '@/types/scene'
|
||||
import type { AnimatableProps, Asset, Layer, Scene } from '@/types/scene'
|
||||
import { sampleLayer } from './interpolate'
|
||||
|
||||
export async function loadSceneImages(scene: Scene): Promise<Record<string, HTMLImageElement>> {
|
||||
@@ -24,6 +24,62 @@ export async function loadSceneImages(scene: Scene): Promise<Record<string, HTML
|
||||
return result
|
||||
}
|
||||
|
||||
interface ShadowState {
|
||||
sx: number
|
||||
sy: number
|
||||
blur: number
|
||||
color: string
|
||||
}
|
||||
|
||||
function hexToRgba(hex: string, alpha: number): string {
|
||||
const h = hex.trim().replace('#', '')
|
||||
const full = h.length === 3 ? h.split('').map((c) => c + c).join('') : h
|
||||
if (full.length < 6) return `rgba(0, 0, 0, ${alpha})`
|
||||
const n = parseInt(full.slice(0, 6), 16)
|
||||
if (Number.isNaN(n)) return `rgba(0, 0, 0, ${alpha})`
|
||||
const r = (n >> 16) & 255
|
||||
const g = (n >> 8) & 255
|
||||
const b = n & 255
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`
|
||||
}
|
||||
|
||||
function computeShadow(p: AnimatableProps): ShadowState | null {
|
||||
const opacity = p.shadowOpacity ?? 0
|
||||
if (opacity <= 0) return null
|
||||
const blur = p.shadowBlur ?? 0
|
||||
const distance = p.shadowDistance ?? 0
|
||||
if (blur <= 0 && distance <= 0) return null
|
||||
const angle = p.shadowAngle ?? 90
|
||||
const rad = (angle * Math.PI) / 180
|
||||
return {
|
||||
sx: Math.cos(rad) * distance,
|
||||
sy: Math.sin(rad) * distance,
|
||||
blur,
|
||||
color: hexToRgba(p.shadowColor ?? '#000000', opacity),
|
||||
}
|
||||
}
|
||||
|
||||
function applyShadow(ctx: CanvasRenderingContext2D, s: ShadowState | null) {
|
||||
if (!s) {
|
||||
ctx.shadowColor = 'transparent'
|
||||
ctx.shadowBlur = 0
|
||||
ctx.shadowOffsetX = 0
|
||||
ctx.shadowOffsetY = 0
|
||||
return
|
||||
}
|
||||
ctx.shadowColor = s.color
|
||||
ctx.shadowBlur = s.blur
|
||||
ctx.shadowOffsetX = s.sx
|
||||
ctx.shadowOffsetY = s.sy
|
||||
}
|
||||
|
||||
function clearShadow(ctx: CanvasRenderingContext2D) {
|
||||
ctx.shadowColor = 'transparent'
|
||||
ctx.shadowBlur = 0
|
||||
ctx.shadowOffsetX = 0
|
||||
ctx.shadowOffsetY = 0
|
||||
}
|
||||
|
||||
function drawLayers(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
layers: Layer[],
|
||||
@@ -44,18 +100,29 @@ function drawLayers(
|
||||
ctx.rotate((p.rotation * Math.PI) / 180)
|
||||
ctx.scale(p.scaleX, p.scaleY)
|
||||
|
||||
const shadow = computeShadow(p)
|
||||
applyShadow(ctx, shadow)
|
||||
|
||||
if (asset.kind === 'rect') {
|
||||
const offX = layer.offsetX ?? asset.width / 2
|
||||
const offY = layer.offsetY ?? asset.height / 2
|
||||
ctx.fillStyle = p.fill ?? asset.fill
|
||||
const fill = p.fill ?? asset.fill
|
||||
const blur = p.blur ?? asset.blur ?? 0
|
||||
ctx.fillStyle = fill
|
||||
if (blur > 0) ctx.filter = `blur(${blur}px)`
|
||||
ctx.fillRect(-offX, -offY, asset.width, asset.height)
|
||||
ctx.filter = 'none'
|
||||
} else if (asset.kind === 'circle') {
|
||||
const offX = layer.offsetX ?? 0
|
||||
const offY = layer.offsetY ?? 0
|
||||
ctx.fillStyle = p.fill ?? asset.fill
|
||||
const fill = p.fill ?? asset.fill
|
||||
const blur = p.blur ?? asset.blur ?? 0
|
||||
ctx.fillStyle = fill
|
||||
if (blur > 0) ctx.filter = `blur(${blur}px)`
|
||||
ctx.beginPath()
|
||||
ctx.arc(-offX, -offY, asset.radius, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
ctx.filter = 'none'
|
||||
} else if (asset.kind === 'text') {
|
||||
const offX = layer.offsetX ?? 0
|
||||
const offY = layer.offsetY ?? 0
|
||||
@@ -72,6 +139,7 @@ function drawLayers(
|
||||
}
|
||||
}
|
||||
|
||||
clearShadow(ctx)
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user