---- AI试用 ---域名问题某些图片和js资源无法访问,导致一些代码实例无法运行!(代码里gzui.net换成momen.vip即可)

canvas学习之canvas实现粒子动画效果

前端开发 蚂蚁 393℃

https://juejin.cn/post/7066828430267908109

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>canvas实现粒子动画效果</title>
    <style>
        html {
            width: 100%;
            height: 100%;
        }

        body {
            height: 100%;
            width: 100%;
        }

        * {
            margin: 0;
            padding: 0;
        }
        #myCanvas{
            position: fixed;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <canvas id="myCanvas" width=""></canvas>
    <script>
        // 获取canvas标签
        let canvas = document.getElementById("myCanvas");

        // 初始化画布的宽高,根据浏览器窗口的宽高来初始化,并且保存浏览器宽高(这里主要是为了后续在浏览器边缘的碰撞检测处使用)
        let width = (canvas.width = window.innerWidth);
        let height = (canvas.height = window.innerHeight);

        // 获取canvas上下文(画笔)
        let ctx = canvas.getContext("2d");

        // 工具函数
        function random(min, max) {
            let num = Math.floor(Math.random() * (max - min) + min);
            if (num === 0) {
                num = 1;
            }
            return num;
        }
        // 随机生成颜色 (rgb)
        function randomColor() {
            return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`;
        }

        // 实现小球类
        /**
         * @param {number} x 横坐标
         * @param {number} y 纵坐标
         * @param {number} vx 沿横轴方向的速度 (可以为负数)
         * @param {number} vy 沿纵轴方向的速度(可为负数)
         * @param {number} size 小球的半径
         * @param {string} color 颜色
         * @param {string} line 线条颜色
         *
         */

        function Ball(x, y, vx, vy, size, color, line) {
            this.x = x;
            this.y = y;
            this.vx = vx;
            this.vy = vy;
            this.size = size;
            (this.color = color), (this.lineColor = line);
        }

        // 绘制当前小球对象的方法
        Ball.prototype.draw = function () {
            // console.log('this',this);
            // 开始绘制(路径)
            ctx.beginPath();
            // 设置画笔的填充颜色
            ctx.fillStyle = this.color;

            // 根据坐标绘制小球
            ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);

            // 填充
            ctx.fill();
        };

        // 更新小球的状态,让小球动起来
        Ball.prototype.update = function () {
            // 检查当前小球的X坐标加上当前的小球半径是否大于浏览器宽度(右边缘碰撞检测)
            // 检查当前小球的X坐标加上当前的小球半径是否小于0(左边缘碰撞检测)
            // 上述的两个条件如果满足其中一个,就需要调转方向(X轴速度vx设置为当前vx的相反数)
            if (this.x + this.size >= width || this.x - this.size <= 0) {
                this.vx = -this.vx;
            }

            // 检查当前小球的Y坐标加上当前的小球半径是否大于浏览器高度(下边缘碰撞检测)
            // 检查当前小球的Y坐标加上当前的小球半径是否小于0(上边缘碰撞检测)
            // 上述的两个条件如果满足其中一个,就需要调转方向(Y轴速度vy设置为当前vy的相反数)
            if (this.y + this.size >= height || this.y - this.size <= 0) {
                this.vy = -this.vy;
            }

            // 根据速度值改动小球的坐标
            this.x += this.vx;
            this.y += this.vy;
        };

        // 生成小球对象列表
        let list = [];
        for (let i = 0; i <= 90; i++) {
            let circle = new Ball(
                // x, y, vx, vy, size, color, line
                /**
                 * @param {number} x 横坐标
                 * @param {number} y 纵坐标
                 * @param {number} vx 沿横轴方向的速度 (可以为负数)
                 * @param {number} vy 沿纵轴方向的速度(可为负数)
                 * @param {number} size 小球的半径
                 * @param {string} color 颜色
                 * @param {string} line 线条颜色
                 *
                 */
                random(0, width),
                random(0, height),
                random(-6, 6) * (1 / 3.0),
                random(-6, 6) * (1 / 3.0),
                3,
                "rgb(255,255,255)",
                `rgba(${random(0, 255)},${random(0, 255)},${random(0, 255)}`
            );
            list.push(circle);
        }
        // console.log('list', list);

        // 循环函数
        function loopCircle() {
            // 刷新画布
            ctx.fillStyle = "rgba(0,0,0,0.6)";
            ctx.fillRect(0, 0, width, height);

            // 双重循环
            // 这里主要是为了计算小球之间的一个二维空间距离,性能不高,有很大的优化空间,读者有兴趣可以自行优化
            for (let i = 0; i < list.length; i++) {
                for (let j = 0; j < list.length; j++) {
                    // 计算当前小球的距离
                    let lx = list[j].x - list[i].x;
                    let ly = list[j].y - list[i].y;
                    let LL = Math.sqrt(Math.pow(lx, 2) + Math.pow(ly, 2));

                    //比对:当距离满足时,绘制线条,以rgba实现过渡
                    if (LL <= 180) {
                        ctx.beginPath();

                        // 这里补足了前面的半截rgba线条颜色
                        ctx.strokeStyle = `${list[i].lineColor},${(180 - LL) / 180})`;

                        // 绘制线条
                        ctx.moveTo(list[i].x, list[i].y);
                        ctx.lineWidth = 1;
                        ctx.lineTo(list[j].x, list[j].y);
                        ctx.stroke();
                    }
                }

                // 绘制小球
                list[i].draw();

                // 更新坐标
                list[i].update();
            }

            // 执行动画(这里传入函数自身后,该回调函数会在浏览器下一次重绘之前再次执行)
            requestAnimationFrame(loopCircle);
        }
        // 开始运行
        loopCircle();
    </script>
</body>

</html>

转载请注明:有爱前端 » canvas学习之canvas实现粒子动画效果

喜欢 (2)or分享 (0)