1. 首页
  2. css

CSS使用Canvas向DOM元素添加粒子效果

让我们看看如何通过将<canvas>的自由性与HTML元素结合起来,使网页更具视觉效果。具体来说,我们将创建一个基本的HTML到粒子效果,但是相同的技术可以用于多种效果。

在开始之前,请随意获取repo中的源代码。

查看repo

创建初始元素

首先,让我们创建一个HTML元素来进行构建。我使用的是一个简单样式的按钮,但它实际上可以是任何HTML元素。

查看这些演示需要Chrome、Firefox或Edge等现代浏览器。

但是如何让画布\”看到\”这个元素,以便使用画布操作每个像素?为了实现这一点,我们基本上需要拍摄HTML元素的快照,就像一个\”打印屏幕\”,但只针对我们要在画布中操作的特定元素(按钮)。

为我们的元素创建一个画布版本

尽管浏览器没有本地的方式来完成这项工作,并允许我们在JavaScript中操作它,但是有一个非常方便的库html2canvas可以帮到我们。我们所要做的就是加载库,然后调用html2canvas(element),它将返回Promise以及我们元素的画布版本!太棒了。

我们的按钮旁边有一个HTML版本和一个canvas版本。我们可以使用canvas版本作为\”屏幕截图\”和信息源,例如特定位置的像素颜色。

从画布获取数据

为此,让我们创建一个新函数来获取特定位置的像素信息。我们也不需要显示从中获取颜色数据的画布,因为我们希望显示原始的HTML元素。

function getColorAtPoint(e) {// Get the coordinate of the clicklet = e.offsetY;// Get the color data of the canvas version of our element at that locationlet>

Now we need to create a canvas particle using that information.

Create a canvas for displaying particles

We don\"t really have a canvas to put the particles on yet because we want to reserve the canvas that we got from html2canvas for accessing color information only. So let\"s create another:

var particleCanvas, particleCtx;function createParticleCanvas() {// Create our = particleCanvas.getContext(\"2d\");// Size our = window.innerHeight;// Position out = = \"1001\";// Make sure other elements under it are>

Get coordinate data

We also need to continue to get the color data from our local coordinate — not only the top and left of our button, but also the position in global coordinates (in relation to the entire web page) in order to create the particle in the right place on the canvas.

We can do so using the following:

btn.addEventListener(\"click\", = e.offsetX;let = ctx.getImageData(localX, localY, 1, 1).data;// Get the button\"s positioning in terms of the windowlet = bcr.left + localX;let>

Create a particle prototype

And let\"s also create a basic particle that has a draw function using variables:

/* An \"exploding\" particle effect that uses circles */var = 1000; // in ms// Set the speed for our = 5 + Math.random() * 5;// Set a max time to live for our = this.life;// This function will be called by our animation logic later => {let = \"rgba(\" + this.rgbArray[0] + \",\" + this.rgbArray[1] + \",\" + this.rgbArray[2] + \", 1)\";ctx.fill();// Update the particle\"s location and lifep.remainingLife--;p.radius += p.speed.x;p.startY += p.speed.y;}}}

创建粒子工厂

我们还需要一个函数来根据一些坐标和颜色信息创建这些粒子,确保我们将它们添加到创建的粒子数组中:

var = new = = Date.now();particles.push(particle);}

添加动画逻辑

我们还需要一种方法来为创建的任何粒子设置动画。

function update() {// Clear out the old particlesif(typeof particleCtx !== \"undefined\") {particleCtx.clearRect(0, 0, window.innerWidth, window.innerHeight);}// Draw all of our particles in their new locationfor(let === particles.length - 1) {let = [];}}}// Animate performantlywindow.requestAnimationFrame(update);}window.requestAnimationFrame(update);

将这些片段放在一起,我们现在可以在单击HTML元素时基于它创建粒子!

每次单击按钮时,一个粒子从按钮中射出。

整洁!

如果我们想在点击时\"分解\"整个按钮,而不是仅仅一个像素,我们只需要修改我们的点击功能:

let => {// Get the color data for our buttonlet = btn.offsetHeightlet = 0;// Go through every location of our button and create a particlefor(let = 0; localY < height; localY++) {if(count % reductionFactor === 0) {let = colorData.slice(index, index + 4);let = bcr.left + localX;let>
Now the button appears to explode into many tiny particles when clicked.

Hopefully, the web now feels less restrictive than it did at the start of this article now that we know we can use additions (like canvas) to exercise more creative freedom.


We can get even more creative by using edge detection to tell if our element is outside of the bounds of a container (i.e. hidden from view) and create particles when our element goes outside of those bounds.

A whole article could be written on this process because positioning of elements in a web browser is complex, but I\"ve created a small plugin called Disintegrate that includes handling for this sort of thing.

Disintegrate: A plugin to create this effect for for you

Disintegrate is open source and handles a lot of the messiness that getting production-ready code for this technique requires. It also allows for multiple elements to apply this effect on the same page, specified containers to be used, a way to ignore specified colors, if needed, and events for the different important moments in the process.

View Repo

Using Disintegrate, we just have to declare> on our button and it will make it so that when our element goes outside its container\"s bounds, particles will be created! See the demo for yourself.

Disintegrate\"s contain effect on a draggable element.

A different type of effect we can make using Disintegrate is where the container is directly surrounding our element. This allows for self-contained particle animations like the button effect we made earlier. By animating the container and our main element itself, we can create particles in even more interesting ways.

A slide to unlock animation triggers exploding particles at the end.

However, this approach does have its limitations (and so does Disintegrate). For example, it will only work back to IE11 due to the lack of pointer-events在此之前支持(前提是分解被编译为ES5)。由于html2canvas的局限性,Dissectigate也不支持我们所能想象到的所有DOM元素。我发现最受限制的是不完整的CSS转换支持和缺少剪辑路径支持。

若要安装dispariate,如果使用npm,可以使用npm install disintegrate。也可以手动包含html2画布.js以及分解.js打电话给disintegrate.init()之前。

分解是非常新的,需要一些改进。如果你愿意贡献,departimate和html2canvas都是开源的,欢迎你的建议!

您认为如何在您的项目中使用此功能?您如何看待这种方法扩展了网络上的可能性?请在评论中告诉我

CSS使用Canvas向DOM元素添加粒子效果 为WP2原创文章,链接:https://www.wp2.cn/css/css%e4%bd%bf%e7%94%a8canvas%e5%90%91dom%e5%85%83%e7%b4%a0%e6%b7%bb%e5%8a%a0%e7%b2%92%e5%ad%90%e6%95%88%e6%9e%9c/

发表评论

您的电子邮箱地址不会被公开。