《Canvas 炫酷动态粒子连线:从零打造流动星空特效》

简单效果图

许多读者一开始看到这个效果便望而生畏,其实想要实现上面的效果非常简单,接下来我会带着大家使用canvas,一步一步实现各种效果

一、技术实现原理

本案例通过 HTML5 Canvas 结合动态算法,实现具有以下特性的粒子系统:

  • 动态粒子运动:每个粒子具备随机速度与边界反弹机制

  • 智能连线交互:自动检测邻近粒子并绘制渐变透明连线

  • 响应式布局:窗口尺寸变化时自动重置画布和粒子分布 [2][4]

二、代码结构解析

1. HTML 基础框架

html 复制代码
<!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>
        canvas {
            position: fixed;
            left: 0;
            top: 0;
            background: #222;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <script src="./index.js"></script>
</body>
</html>
  • <meta name="viewport">确保移动端显示适配

  • Canvas 通过 CSS 实现全屏固定定位

  • 外部 JS 文件分离实现模块化开发

2. 核心 JS 模块

(1) 初始化模块
js 复制代码
const cvs = document.querySelector('canvas');
ctx = cvs.getContext('2d');

function init() {
    cvs.width = window.innerWidth;
    cvs.height = window.innerHeight;
}
  • getContext('2d')获取 2D 渲染上下文

  • 动态设置画布尺寸适配屏幕分辨率

(2) 粒子类 (Point)
js 复制代码
class Point {
    constructor() {
        this.r = 6; // 粒子半径
        this.x = getRandom(this.r, cvs.width - this.r); // X轴随机位置
        this.y = getRandom(this.r, cvs.height - this.r); // Y轴随机位置
        this.vx = getRandom(-0.5, 0.5); // X轴速度
        this.vy = getRandom(-0.5, 0.5); // Y轴速度
    }

    update() {
        // 边界反弹检测
        if (this.x < this.r || this.x > cvs.width - this.r) this.vx *= -1;
        if (this.y < this.r || this.y > cvs.height - this.r) this.vy *= -1;
        this.x += this.vx;
        this.y += this.vy;
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        ctx.fillStyle = '#fff';
        ctx.fill();
    }
}
  • 粒子对象封装运动轨迹与绘制方法

  • 速度取反实现边界反弹效果

(3) 图形控制器 (Graph)
js 复制代码
class Graph {
    constructor() {
        this.points = new Array(100).fill(0).map(() => new Point());
        this.maxDis = 200; // 最大连线距离
        this.animate();
    }

    animate() {
        ctx.clearRect(0, 0, cvs.width, cvs.height);
        this.points.forEach(p => p.update());
        this.draw();
        requestAnimationFrame(() => this.animate());
    }

    draw() {
        this.points.forEach((p1, i) => {
            p1.draw();
            this.points.slice(i + 1).forEach(p2 => {
                const d = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
                if (d > this.maxDis) return;
                
                ctx.beginPath();
                ctx.moveTo(p1.x, p1.y);
                ctx.lineTo(p2.x, p2.y);
                ctx.strokeStyle = `rgba(255, 255, 255, ${1 - d / this.maxDis})`;
                ctx.stroke();
            });
        });
    }
}
  • requestAnimationFrame实现 60FPS 流畅动画

  • 距离检测算法优化性能(O (n²) → 分片遍历)

三、关键技术亮点

  1. 运动轨迹优化

    • 速度随机值范围控制在 [-0.5, 0.5]
    • 距离检测公式:Math.sqrt(Δx² + Δy²)
  2. 视觉效果增强

    • 连线透明度与距离成反比:1 - d/maxDis
    • 黑色背景与白色粒子形成高对比度
  3. 响应式处理

  • 窗口尺寸变化时重新初始化粒子位置
js 复制代码
window.addEventListener('resize', () => {
    init();
    g.points.forEach(p => {
        p.x = getRandom(p.r, cvs.width - p.r);
        p.y = getRandom(p.r, cvs.height - p.r);
    });
});
相关推荐
zwjapple3 小时前
docker-compose一键部署全栈项目。springboot后端,react前端
前端·spring boot·docker
像风一样自由20205 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem6 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊6 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术6 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing6 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止6 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall6 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴6 小时前
简单入门Python装饰器
前端·python
袁煦丞7 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作