需求
- 准备有轮播动画一帧帧的图片,使用
canvas
实现轮播动画
思路
- 动态加载图片,存入到一个数组中。图片是异步加载的,确保数组中存入的图片顺序与图片帧的顺序一致
- 所有图片加载完成后,开始绘制
- 使用
canvas
+ requestAnimationFrame
实现图片轮播显示
实现
- 在
src/main.js
文件中对requestAnimationFrame
做兼容处理
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame||
window.oRequestAnimationFrame ||
function (callback) {
return setTimeout(callback, Math.floor(1000 / 60))
}
)
}
- 在
src/utils/canvas.js
文件中定义几个常用的方法
export function loadImages (images) {
return new Promise((resolve, reject) => {
let arr = []
let loadedImages = -1
let numImages = images.length - 1
images.forEach(item => {
let img = new Image()
img.src = item
arr.push(img)
img.onload = () => {
loadedImages++
if (loadedImages === numImages) {
resolve(arr)
}
}
})
})
}
export function loadPlanet () {
let data = []
for (let i = 1; i <= 120; i++) {
data.push(`static/images/planet/${i}.png`)
}
return loadImages(data)
}
<div>
<canvas ref="canvasPlanet"></canvas>
</div>
import { loadPlanet } from 'utils/canvas'
export default {
data() {
return {
canvas: null,
ctx: null,
speed: 2,
index: 0,
images: []
}
},
async mounted() {
this.images = await loadPlanet()
this.initCanvas()
this.executeFrame()
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvasPlanet
this.ctx = this.canvas.getContext('2d')
const parent = this.canvas.parentElement
this.canvas.width = parent.offsetWidth
this.canvas.height = parent.offsetHeight
},
executeFrame() {
if (this.canvas.width !== window.innerWidth || this.canvas.width !== window.innerWidth) {
this.initCanvas()
}
this.speed--
if (this.speed === 0) {
this.speed = 2
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.ctx.drawImage(this.images[this.index], 0, 0, this.canvas.width, this.canvas.height)
this.index = this.index >= this.images.length - 1 ? 0 : this.index + 1
}
window.requestAnimationFrame(this.executeFrame)
}
}
}
发表评论