Skip to content

Instantly share code, notes, and snippets.

@mauriciomassaia
Last active February 24, 2022 06:57
Show Gist options
  • Save mauriciomassaia/2343d4e45d046077e8f902e029167cdf to your computer and use it in GitHub Desktop.
Save mauriciomassaia/2343d4e45d046077e8f902e029167cdf to your computer and use it in GitHub Desktop.
Spritesheet Animation class with Typescript and TexturePacker
// Generic JSON data spritesheet
export interface Rect {
x: number
y: number
w: number
h: number
}
export interface Frame {
filename: string
frame: Rect
rotated: boolean
trimmed: boolean
spriteSourceSize: Rect
sourceSize: Size
}
export interface Size {
w: number
h: number
}
export interface Meta {
app: string
version: string
image: string
format: string
size: Size
scale: string
smartupdate: string
}
export interface SpritesheetData {
frames: Frame[]
meta: Meta
}
import { SpritesheetData } from './interfaces'
// generate a spritesheet (png + json) using TexturePacker data file format JSON (Array)
export class SpritesheetAnimation {
canvas: HTMLCanvasElement
protected image = new Image()
protected ctx: CanvasRenderingContext2D
private playing = false
private frameIndex = 10
protected data: SpritesheetData
constructor () {
this.update = this.update.bind(this)
this.image.src = './spritesheets/animation.png'
this.canvas = document.createElement('canvas')
this.canvas.width = 1000
this.canvas.height = 200
const ctx = this.canvas.getContext('2d')
if (ctx === null) {
throw new Error('Animation - Invalid 2d context')
}
this.ctx = ctx
this.loadData()
.catch(console.error)
}
private async loadData (): Promise<void> {
const response = await fetch('./spritesheets/animation.json')
this.data = await response.json() as SpritesheetData
this.open()
}
open (): void {
// add fade in
if (this.playing) return
this.playing = true
this.update()
}
close (): void {
// add fade out
if (!this.playing) return
this.playing = false
}
private drawFrame (): void {
const index = Math.floor(this.frameIndex)
const { frame, spriteSourceSize } = this.data.frames[index]
this.ctx.clearRect(0, 0, 1000, 200)
this.ctx.fillStyle = 'rgba(0, 0, 0,0)'
this.ctx.drawImage(
this.image,
frame.x,
frame.y,
frame.w,
frame.h,
spriteSourceSize.x,
spriteSourceSize.y,
spriteSourceSize.w,
spriteSourceSize.h
)
}
private update (): void {
this.frameIndex += 1
this.frameIndex %= this.data.frames.length
this.drawFrame()
if (this.playing) {
window.requestAnimationFrame(this.update)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment