《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);
    });
});
相关推荐
qq. 28040339848 小时前
CSS层叠顺序
前端·css
喝拿铁写前端8 小时前
SmartField AI:让每个字段都找到归属!
前端·算法
猫猫不是喵喵.8 小时前
vue 路由
前端·javascript·vue.js
烛阴8 小时前
JavaScript Import/Export:告别混乱,拥抱模块化!
前端·javascript
bin91539 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例12,TableView16_12 拖拽动画示例
前端·javascript·vue.js·ecmascript·deepseek
GISer_Jing9 小时前
[Html]overflow: auto 失效原因,flex 1却未设置min-height &overflow的几个属性以及应用场景
前端·html
程序员黄同学9 小时前
解释 Webpack 中的模块打包机制,如何配置 Webpack 进行项目构建?
前端·webpack·node.js
拉不动的猪9 小时前
vue自定义“权限控制”指令
前端·javascript·vue.js
再学一点就睡9 小时前
浏览器页面渲染机制深度解析:从构建 DOM 到 transform 高效渲染的底层逻辑
前端·css
拉不动的猪10 小时前
刷刷题48 (setState常规问答)
前端·react.js·面试