最近逛掘金看见了蛮多人在做烟花特效,毕竟烟花爆竹是过年标志性物件,生活中国家规定不允许放烟花,所以用代码过一下视觉效果瘾还是比较爽的。 看到社区里面的大佬写的烟花特效时突然就有一个想法从我脑中浮现,烟花除了爆炸形状能不能展示一些不一样的呢?比如文字?基于这个想法就产生了今天要分享的内容。
整体思路
这种的效果一般思路都是如下:
- 绘制一个烟花发射的点
- 该点达到某个高度后,使之隐藏
- 基于高度点位,绘制出不同形状的点位向量
所以能得到形状的点位数据那烟花爆炸后的效果就能随心所欲的发挥了。 比如我想在爆炸后出现“陈”的形状,那“陈”的点位数据如何得到呢?我是把文字绘制到一个canvas上,根据getImageData方法获取整个canvas的像素数据,筛选出有颜色(非透明)点位数据就是组成我们“陈”的点位数据,获取到这些数据后我还计算了这些点位与canvas中心点的夹角方便之后做动效用。具体代码如下。
/** * * @param {number} x 发射点最高的横坐标 * @param {number} y 发射点最高的纵坐标 * @param {string} value 待绘制的文字 * @returns */ getFontPosition(x, y, value) { let fontWidth = value.length * 24; let canvas = document.createElement("canvas"); canvas.height = fontWidth; canvas.width = fontWidth; let canvasContent = canvas.getContext("2d"); canvasContent.font = "24px Arial"; canvasContent.clearRect(0, 0, fontWidth, 40); canvasContent.textBaseline = "middle"; canvasContent.fillText(value, 0, fontWidth / 2); let centerBase = fontWidth / 2; let data = canvasContent.getImageData(0, 0, fontWidth, fontWidth).data; let positionArray = []; for (let height = 0; height < fontWidth; height += 2) { for (let width = 0; width < fontWidth; width += 2) { let index = (height * fontWidth + width) * 4; if (data[index + 3]) { positionArray.push({ x: x + (width - centerBase) * 8, // 把原来的坐标都扩大8倍 y: y + (height - centerBase) * 8, size: 1, speed: 0.15, direction: Math.atan2(height - centerBase, width - centerBase), color: `${~~(Math.random() * 256)},${~~(Math.random() * 256)},${~~( Math.random() * 256 )}` }); } } } return positionArray; }
到此最关键的一步的就完成,剩下的就是让这些点跟随时间做一些动效就不展开讲了,可以去看看这篇文章-> 传送门。
附上一个在线demo地址。
代码已经同步到git上了,有需要的小伙伴可以去看下。
最后祝大家新年快乐 :)