Skip to content

粒子动画

源代码

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

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            html,
            body {
                margin: 0;
                padding: 0;
                overflow: hidden;
                width: 100%;
                height: 100%;
            }

            #canvas {
                display: block;
                background: #333;
            }
        </style>
    </head>

    <body>
        <canvas id="canvas"></canvas>
        <script>
            // 获取canvas元素
            const canvas = document.getElementById('canvas');
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                alert('当前浏览器不支持Canvas');
            }
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            class Point {
                constructor() {
                    this.r = 6;
                    this.x = getRandom(0, canvas.width - this.r / 2);
                    this.y = getRandom(0, canvas.height - this.r / 2);
                    this.xSpeed = getRandom(-50, 50);
                    this.ySpeed = getRandom(-50, 50);
                    this.lastDrawTime = null
                }
                draw(ctx) {
                    if(this.lastDrawTime) {
                        const duration = (Date.now() - this.lastDrawTime) / 1000;
                        this.x += this.xSpeed * duration;
                        this.y += this.ySpeed * duration;
                        if (this.x <= this.r || this.x >= canvas.width - this.r) {
                            this.xSpeed = -this.xSpeed;
                        }
                        if (this.y <= this.r || this.y >= canvas.height - this.r) {
                            this.ySpeed = -this.ySpeed;
                        }
                    }
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
                    ctx.fillStyle = '#ff0';
                    ctx.fill();
                    this.lastDrawTime = Date.now();
                }
            }

            // 随机数
            function getRandom(min, max) {
                return Math.random() * (max - min) + min;
            }

            class Graphic {
                constructor(maxPoints = 30) {
                    this.points = Array.from({ length: maxPoints }).map(() => new Point());
                }
                draw(ctx) {
                    requestAnimationFrame(() => this.draw(ctx));
                    ctx.clearRect(0, 0, canvas.width, canvas.height);

                    this.points.forEach((point, index) => {
                        point.draw(ctx);
                        this.points.forEach((otherPoint, otherIndex) => {
                            if (index !== otherIndex) {
                                // 计算 透明度 如果距离越近 透明度越大
                                const dx = point.x - otherPoint.x;
                                const dy = point.y - otherPoint.y;
                                const distance = Math.sqrt(dx * dx + dy * dy);
                                const threshold = distance / 500

                                ctx.beginPath();
                                ctx.moveTo(point.x, point.y);
                                ctx.lineTo(otherPoint.x, otherPoint.y);
                                ctx.strokeStyle = `rgba(255,255,255,${1 - threshold})`;
                                ctx.stroke();
                            }
                        });
                    });
                }
            }

            const graphic = new Graphic();
            graphic.draw(ctx);
        </script>
    </body>

    </html>

运行效果