一、canvas动画核心概念
完全没有canvas基础的同学建议先刷一下 [Canvas的基本用法 - Web API 接口参考 | MDN]
重点是理解canvas动画的基本步骤,在[基本的动画 - MDN]中,动画分为4步走
初学者可以再简单一些,我们先不管状态保存,直接两步走:
- 清空canvas
- 绘制新的一帧动画
用定时器或者window.requestAnimationFrame
定时重复以上两步即可
二、抢金币核心原理
想象一下整个业务场景,我们先梳理出3个要解决的核心问题:
- 1、生成红包,这里有两种解决方案
- 统一生成所有的红包对象,从上到下分布在y轴,触发运动后后整体向下运动
- 在屏幕上方持续生成新红包对象,红包一旦生成,立刻开始运动(本次选择此方案)
- 2、运动,canvas动画原理
- 3、用户点击红包,计算是否点中红包(事件只能绑定在canvas这一层,需要根据点击位置进行计算)
三、核心功能
- 1、预缓存图片/离屏canvas
- 2、canvas绘制多图,改变每一帧形成动画
- 3、判断点击位置,冒泡+1效果
下面都是基于vue的代码,不能直接跑的,主要用于理解核心功能
最好是自己理解核心原理后亲自动手做个最简单的demo,有助于加深理解
1、预缓存图片/离屏canvas
页面上感觉有很多很多金币在按各种角度掉落
其实页面上一共就4种金币图片,只是他们的大小、速度不一样,看起来有每一个都不一样
我们可以先把这4张图片全都加载好
// 缓存几种金币图片为DOM元素,避免canvas绘制时还需要异步读取图片
loadImgs(arr) {
return new Promise(resolve => {
let count = 0;
// 循环图片数组,每张图片都生成一个新的图片对象
const len = arr.length;
for (let i = 0; i < len; i++) {
// 创建图片对象
const image = new Image();
// 成功的异步回调
image.onload = () => {
count++;
arr.splice(i, 1, {
// 加载完的图片对象都缓存在这里了,canvas可以直接绘制
img: image,
// 这里可以直接生成并缓存离屏canvas,用于优化性能,但本次不用,只是举个例子
offScreenCanvas: this.createOffScreenCanvas(image)
});
// 这里说明 整个图片数组arr里面的图片全都加载好了
if (count == len) {
this.preloaded = true;
resolve();
}
};
image.src = arr[i].img;
}
});
},
复制代码
创建离屏canvas的方法如下
createOffScreenCanvas(image) {
const offscreenCanvas = document.createElement("canvas");
const offscreenContext = offscreenCanvas.getContext("2d");
// 这里可以是动态宽高
offscreenContext.width = 30;
offscreenContext.height = 30;
offscreenContext.drawImage(
image,
0,
0