34 行 JavaScript 代码搞定粒子动画效果

4,413 阅读2分钟
原文链接: svgtrick.com

34行JavaScript代码真的能搞定一个粒子动画系统吗?

在web网页开发中,像这种使用粒子动画作为网页背景的情形非常常见。如下图所示:

但是要实现它看起来貌似很复杂,我曾经看到过一个使用150行代码实现的一个粒子动画效果!本篇文章就是要来实现这样一个粒子动画效果,并不需要这么多代码,仅仅34行就可以了。当然,这个效果就是一个单纯的粒子动画效果,没有交互,没有矢量,没有加速度,但是完全够用了。

开始吧

开始之前,你需要一点基本的Canvas的知识。

首先来分析下,这个动画效果所涉及到的一些变量:

1、速度

2、透明度

3、粒子的尺寸

以及粒子撞击到视图边界后,往反的方向移动。

初始化设置

首先来建一个基本的骨架。

HTML

<canvas id=c></canvas>

CSS

canvas {
    position: absolute;
    top: 0px;
    left: 0px;
}

JavaScript

(()=>{
    let $ = c.getContext("2d"),
        w = c.width = window.innerWidth,
        h = c.height = window.innerHeight,
        //predefines...
})()

上面的代码定义了一个立即执行方法,并且定义了一些基础的变量。wh即canvas的宽和高等于浏览器可视窗口的宽和高。

let pi2 = Math.PI*2,
            random = t=>Math.random()*t,
            binRandom = t=>Math.random()<t;

这段代码主要是用来创建随机数用的,在后面将会用到它们。接下里就是在屏幕上绘制粒子:

function draw(){
        $.fillStyle="#222";
        $.fillRect(0,0,w,h);
        requestAnimationFrame(draw);
    }
    draw(); //do not forget to call the function

这个方法主要是来定义绘制粒子的一些属性,比如颜色、宽高等。下面就一步一步来绘制粒子使粒子动起来。

先来看下粒子的一些属性:

1、尺寸

2、位置

3、运动速度

4、透明度

我们把粒子的这些属性全部定义在一个数组里面:

let arr = new Array(500 /* amount */).fill().map(p=>{
    return {
        p: {x: random(w), y: random(h) }, //position
        v: { //velocity
            x: binRandom(0.5)? random(1) : random(-1),
            y: binRandom(0.5)? random(1) : random(-1)
        },
        s: random(1)+2, //size
        o: random(1)+.3 //opacity
    }
})

下面就来分析下上面的代码。

1、首先我们创建了一个空的数组。map()方法会遍历数组中的元素并且返回一些指定的值。当然,现在还不能执行这个方法,因为数组是空的。

2、fill()方法则是用于将一个固定值替换数组的元素。

4、粒子的位置position是根据屏幕的宽和高和已经定义好的random方法来计算的。

5、Velocity这个参数主要是用来当粒子撞向可视窗口边缘的时候,使它运动的更加自然而设置的。

6、Size粒子的尺寸也是随机分配的。

7、Opacity,使用透明度是为了使粒子有一个很好的区分。随机分配粒子的透明度的值在.31.3之间。

接下来使渲染绘制粒子。

function draw(){
    //stuff
    arr.forEach(p=>{
        $.fillStyle="rgba(255,255,255,"+p.o+")";
        $.beginPath();
        $.arc(p.p.x, p.p.y, p.s, 0, pi2);
        $.closePath();
        $.fill();
    })
}

这就不用多解释了,就是用canvas提供的基本的方法来绘制粒子。这里用到的颜色、透明度、位置等直接就是已经在数组中定义好的。

粒子绘制好了,还差最后一步,就是让粒子动起来。

arr.forEach(p=>{
    p.p.x += p.v.x;
    p.p.y += p.v.y;
    if (p.p.x > w || p.p.x < 0) p.v.x *= -1;
    if (p.p.y > h || p.p.y < 0) p.v.y *= -1;
    //rendering stuff
}

上面的代码是用来检测粒子是否已经运动到了可视窗口的边界,如果是,则往反的方向运动。

到这里为止,只花了30行代码就实现了一个简单的粒子动画效果。

在codepen上,有很多非常聪明的程序员。比如在我上一篇教程中,我通过eventListener来监听窗口是否缩放,而Mark (@Blindman67)就建议可以用一行代码来代替原来使用eventListener才能达到的目的。

(h !== innerHeight || w!==innerWidth) && (w=c.width=innerWidth,h=c.height=innerHeight);

非常的巧妙,就这样仅仅只需要34行代码就完成了粒子动画效果。

本文主要是从Bouncing Particles are not complicated这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!