import { Vector } from "../geometry/vector.ts"; import { Frame, handleGIF } from "../processing/gif.ts"; type frame = { canvas: HTMLCanvasElement } & Frame; export class GIFAnimation { frames: frame[] = []; canvas: HTMLCanvasElement; ctx!: CanvasRenderingContext2D; ready = false; constructor( url: string, private origin: Vector, private scale = 1, ) { this.canvas = document.createElement("canvas"); this.init(url); } async init(url: string) { const res = await fetch(url); const buf = new Uint8Array(await res.arrayBuffer()); const gif = handleGIF(buf); this.frames = gif.frames; this.frameTimes = this.frames.map((f) => f.delay); this.totalAnimationTime = this.frameTimes.reduce( (a, b) => a + b, 0, ); this.canvas.width = gif.w; this.canvas.height = gif.h; this.ctx = this.canvas.getContext("2d")!; this.ready = true; } frameTimes!: number[]; totalAnimationTime = 0; _frameCounter = 0; currentFrameIndex = 0; draw(timeSinceLastFrame: number) { if (!this.ready) return; this._frameCounter += timeSinceLastFrame; const currentFrameDelay = this.frames[this.currentFrameIndex].delay * 10; while (this._frameCounter >= currentFrameDelay) { this._frameCounter -= currentFrameDelay; this.currentFrameIndex = (this.currentFrameIndex + 1) % this.frames.length; } const currentFrame = this.frames[this.currentFrameIndex]; doodler.drawImage( currentFrame.canvas, this.origin, this.canvas.width * this.scale, this.canvas.height * this.scale, ); } }