js 实现粒子特效

·  阅读 913
js 实现粒子特效

前言

今天和各位小伙伴分享一下,如何使用canvas实现粒子特效(可用作登录背景)。涉及的知识点如下:

话不多说,直接上代码

实现

CSS

* {
    margin: 0;
    padding: 0;
}

canvas {
    display: block;
}

.log {
    position: fixed;
    top: 5px;
    left: 5px;
    right: 0;
    bottom: 0;
}
复制代码

HTML

<canvas id="canvas"></canvas>
<div class="log"></div>
复制代码

js

// 获取dom
const canvas = document.getElementById('canvas');
const log = document.querySelector('.log');
const ctx = canvas.getContext('2d');
const colors = ['#ed1941', '#f05b72', '#ef4136', '#f15a22', '#8e3e1f', '#fcaf17', '#b76f40', '#00ae9d', '#009ad6', '#1d953f', '#426ab3', '#6950a1', '#74787c', '#2a5caa'];
let w, h;
// 设置canvas宽高
setCanvasSize();
function setCanvasSize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    w = window.innerWidth;
    h = window.innerHeight;
}
window.addEventListener('resize', setCanvasSize);
/**
 * 获取min(包含) - max(不包含)之间的随机数
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns 
 */
function getRandom(min, max) {
    return Math.random() * (max - min) + min;
}
/**
 * 获取两点距离
 * @param {object} a 第一个点的位置
 * @param {object} b 第二个点的位置
 * @returns
 */
function getDistance(a, b) {
    const x = a.x - b.x;
    const y = a.y - b.y;
    return Math.hypot(x, y); // Math.sqrt(x * x + y * y);
}
// 构造函数
function Particle() { }
// 创建粒子函数
Particle.prototype.create = function () {
    // 粒子半径
    this.radius = getRandom(2.2, 4);
    // 粒子位置
    this.x = getRandom(0 + this.radius, w - this.radius);
    this.y = getRandom(0 + this.radius, h - this.radius);
    // 粒子运动速度
    this.speedX = getRandom(-1, 1);
    this.speedY = getRandom(-1, 1);
    // 粒子颜色
    this.color = colors[Math.floor(getRandom(0, colors.length))];
}
// 绘制粒子函数
Particle.prototype.draw = function () {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    ctx.fill();
}
// 连线粒子函数
Particle.prototype.link = function () {
    for (const particle of particles) {
        const distance = getDistance(this, particle);
        if (distance < 150) {
            ctx.beginPath();
            ctx.lineWidth = 0.1;
            ctx.strokeStyle = this.color;
            ctx.moveTo(this.x, this.y);
            ctx.lineTo(particle.x, particle.y);
            ctx.stroke();
        }
    }
}
// 移动粒子函数
Particle.prototype.move = function () {
    // 碰撞边界后反弹
    if (this.x <= this.radius || this.x + this.radius >= w) {
        this.speedX *= -1;
    }
    if (this.y <= this.radius || this.y + this.radius >= h) {
        this.speedY *= -1;
    }
    this.x += this.speedX;
    this.y += this.speedY;
}
// 粒子数组
const particles = [];
for (let i = 0; i < 88; i++) {
    const particle = new Particle();
    particle.create();
    particles.push(particle);
}
// 动画
function raf() {
    let start;
    function step(timestamp) {
        if (start === undefined) {
            start = timestamp;
        }
        const fps = Math.trunc(1000 / (timestamp - start));
        start = timestamp;
        log.innerHTML = `${fps}FPS`;
        // 清空画布
        ctx.clearRect(0, 0, w, h);
        // 更新粒子
        for (const particle of particles) {
            particle.move();
            particle.draw();
            particle.link();
        }
        window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
}
raf();
复制代码

Demo:jsdemo.codeman.top/html/partic…

结语

以上代码实现了最基础的粒子特效。如果还想实现其他炫酷的效果,小伙伴们可在此代码基础之上或参考开源库自行实现。

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改