大漠 2018-07-25 23:01
特别声明,本文根据@ZACH SAUCIER的《Adding Particle Effects to DOM Elements with Canvas》一文整理。
让我们来看看如何将<canvas>
的自由度与HTML元素结合起来,使Web页面在视觉上有更好的效果。具体地说,我们将创建一个基于HTML-to-particle
的效果,但同样的技术也可以用于实现很多类型的效果。
在开始之前,可以通过Repo获取源代码。
创建初始的元素
首先,让我们创建一个HTML元素。这里创建了一个带有简单样式效果的按钮,事实上它可以是任何一个HTML元素。
建议使用Chrome、Firefox或Edge等现代浏览器查看这些Demo效果。
但是,如何让canvas
“看到”这个元素,以便使用canvas
来 操作每个像素 呢?为了实现这一点,需要对HTML元素进行快照 —— 就像“打印屏幕”一样,但只对希望在canvas
中操作的特定元素(比如说按钮)进行快照。
创建canvas
版本的元素
尽管浏览器到目前还无法实现这一点,但庆幸的是允许我们通过JavaScript来操作它,较为出名的html2canvas
库就可以。我们所要做的就是加载这个库,然后调用html2canvas(element)
,它将返回一个Promise
以及一个canvas
版本的元素。是不是很棒。
上面这个示例,我们有一个HTML版本和Canvas版本的按钮。我们可以使用Canvas版本作为我们的“屏幕快照”,并将其作为信息的来涨势,例如特定像素位置的颜色。
从Canvas中获取数据
为此,我们创建一个新函数来获取Canvas中特定位置的像素信息。我们也不需要显示从Canvas中得到的颜色数据,因为我们显示原始的HTML元素。
function getColorAtPoint(e) {
// 获取鼠标点击位置的坐标
let x = e.offsetX;
let y = e.offsetY;
// 获取该位置上颜色数据
let rgbaColorArr = ctx.getImageData(x, y, 1, 1).data;
// rgbaColorArr相关的处理
}
现在我们需要使用这些信息创建一个Canvas的粒子效果。
创建Canvas粒子效果
我们还没有使用Canvas来放置粒子,因为我们想要保留html2canvas
的canvas
用于访问颜色信息。接下来创建粒子效果的函数。
var particleCanvas, particleCtx;
function createParticleCanvas() {
// 创建用于粒子效果的Canvas
particleCanvas = document.createElement("canvas");
particleCtx = particleCanvas.getContext("2d");
// Canvas的大小
particleCanvas.width = window.innerWidth;
particleCanvas.height = window.innerHeight;
// Canvas的位置
particleCanvas.style.position = "absolute";
particleCanvas.style.top = "0";
particleCanvas.style.left = "0";
// 设置Canvas在元素的上面
particleCanvas.style.zIndex = "1001";
// 确保它下面的其他元素是可点击的
particleCanvas.style.pointerEvents = "none";
// 把Canvas添加到页面中
document.body.appendChild(particleCanvas);
}
获取坐标数据
我们还需要从本地坐标系统得到颜色相关的数据 —— 不仅仅是按钮的左上角,而且全局坐标的位置(相对整个Web页面),这样做是为了在Canvas的正确地方创建粒子。
我们可以这样做:
btn.addEventListener("click", e => {
// 获取颜色数据
let localX = e.offsetX;
let localY = e.offsetY;
let rgbaColorArr = ctx.getImageData(localX, localY, 1, 1).data;
// 根据window获取按钮的位置
let bcr = btn.getBoundingClientRect();
let globalX = bcr.left + localX;
let globalY = bcr.top + localY;
// 使用window的位置获取颜色数据,创建一个粒子
createParticleAtPoint(globalX, globalY, rgbaColorArr);
});
创建一个粒子原型
我们还可以创建一个基本粒子,是一个带有参数的绘图函数:
/* 圆形爆炸的粒子效果 */
var ExplodingParticle = function() {
// 设置想要的粒子动画的时长
this.animationDuration = 1000; // in ms
// 设置粒子的速度
this.speed = {
x: -5 + Math.random() * 10,
y: -5 + Math.random() * 10
};
// 粒子大小
this.radius = 5 + Math.random() * 5;
// 为粒子设定一个最大的生存时间
this.life = 30 + Math.random() * 10;
this.remainingLife = this.life;
// 这个函数稍后将会调用动画相关的逻辑
this.draw = ctx => {
let p = this;
if(this.remainingLife > 0
&& this.radius > 0) {
// 在当前位置绘制一个圆
ctx.beginPath();
ctx.arc(p.startX, p.startY, p.radius, 0, Math.PI * 2);
ctx.fillStyle = "rgba(" + this.rgbArray[0] + ','