Skip to content

Instantly share code, notes, and snippets.

@hugohil
Last active September 10, 2020 06:33
Show Gist options
  • Save hugohil/9385910e65177f678b7bb9a101aa76b9 to your computer and use it in GitHub Desktop.
Save hugohil/9385910e65177f678b7bb9a101aa76b9 to your computer and use it in GitHub Desktop.
spritesheet vue component
<template>
<div id="wrapper">
<sprite :id="'sprite'"
:spritesheet="require('../assets/spritesheet.png')"
:json="require('../assets/spritesheet.json')"
:yoyo="false"
:fps="30"
ref="sprite"
></sprite>
<button @click="play">play</button>
<button @click="stop">stop</button>
</div>
</template>
<script>
import Sprite from './Sprite'
export default {
name: 'page',
components: { Sprite },
methods: {
play () {
this.$refs.sprite.play()
},
stop () {
this.$refs.sprite.stop()
}
}
}
</script>
<style></style>
<template lang="html">
<div class="sprite">
<canvas :id='id' :width="width" :height="height" ref="canvas"></canvas>
</div>
</template>
<script>
/*
* Use https://github.com/krzysztof-o/spritesheet.js/
* to generate spritesheet
* with the `jsonarray` format
*/
export default {
name: 'sprite',
props: {
spritesheet: {
required: true,
type: String,
default: ''
},
json: {
required: true,
type: Object,
default: {}
},
fps: {
type: Number,
default: 30
},
autoplay: {
type: Boolean,
default: true
},
yoyo: {
type: Boolean,
default: false
},
id: {
type: String,
default: 'sprite'
}
},
data () {
return {
frames: [],
visible: true,
length: 0,
frameIndex: 0,
currentIndex: 0,
animationFrameID: null,
yoyodirection: 0,
sprite: null,
ctx: null,
height: 0,
width: 0,
now: 0,
then: 0
}
},
mounted () {
console.log(this.json)
this.json.frames.forEach((frame) => {
this.frames.push({
name: frame.filename,
x: frame.frame.x,
y: frame.frame.y,
w: frame.frame.w,
h: frame.frame.h
})
})
this.frames.sort((a, b) => {
return a.filename < b.filename
})
this.width = this.frames[0].w
this.height = this.frames[0].h
this.length = (this.frames.length - 1)
},
created () {
this.$nextTick(() => {
this.sprite = new Image()
this.sprite.src = this.spritesheet
this.sprite.onload = ({ target }) => { this.init(target) }
})
},
methods: {
init (img) {
this.ctx = this.$refs.canvas.getContext('2d')
this.autoplay && this.loop()
},
render () {
this.ctx.clearRect(0, 0, this.width, this.height)
if (this.yoyo && this.currentIndex % this.length === 0 && this.currentIndex) {
this.yoyodirection = Number(!this.yoyodirection)
}
const index = Math.abs((this.currentIndex % this.length) - (this.length * this.yoyodirection))
const x = this.frames[index].x
const y = this.frames[index].y
this.ctx.drawImage(this.sprite, x, y, this.width, this.height, 0, 0, this.width, this.height)
},
loop () {
this.now = Date.now()
const delta = (this.now - this.then)
if (delta > (1000 / this.fps)) {
this.then = this.now - (delta % (1000 / this.fps))
this.render()
this.currentIndex++
}
this.animationFrameID = window.requestAnimationFrame(this.loop)
},
stop () {
window.cancelAnimationFrame(this.animationFrameID)
this.currentIndex = 0
},
play () {
this.loop()
}
}
}
</script>
<style></style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment