HTML5 Canvas交互式粒子动画实现教程 – 前端图形技术

2025-09-21 0 540

100

实现原理

1. Canvas基础设置

首先获取Canvas元素和其2D渲染上下文,这是所有绘图操作的基础:

const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');

2. 粒子对象设计

每个粒子是一个独立对象,包含位置、速度、大小和颜色等属性:

function Particle(x, y) {
    this.x = x;
    this.y = y;
    this.size = Math.random() * 5 + 1;
    this.speedX = Math.random() * 3 - 1.5;
    this.speedY = Math.random() * 3 - 1.5;
    this.color = `hsl(${Math.random() * 360}, 50%, 50%)`;
}

3. 粒子更新与绘制

每个粒子需要更新位置并绘制自身:

Particle.prototype.update = function() {
    this.x += this.speedX;
    this.y += this.speedY;
    
    // 边界检测
    if (this.x > canvas.width || this.x  canvas.height || this.y < 0) {
        this.speedY = -this.speedY;
    }
};

Particle.prototype.draw = function() {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
    ctx.fill();
};

4. 动画循环实现

使用requestAnimationFrame实现平滑动画:

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    // 更新并绘制所有粒子
    for (let i = 0; i < particles.length; i++) {
        particles[i].update();
        particles[i].draw();
    }
    
    // 连接相近的粒子
    connectParticles();
    
    requestAnimationFrame(animate);
}

animate();

5. 粒子间连线效果

当粒子距离较近时,绘制连线形成网状效果:

function connectParticles() {
    for (let i = 0; i < particles.length; i++) {
        for (let j = i; j < particles.length; j++) {
            const dx = particles[i].x - particles[j].x;
            const dy = particles[i].y - particles[j].y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            if (distance < 100) {
                ctx.beginPath();
                ctx.strokeStyle = `rgba(255, 255, 255, ${1 - distance/100})`;
                ctx.lineWidth = 0.5;
                ctx.moveTo(particles[i].x, particles[i].y);
                ctx.lineTo(particles[j].x, particles[j].y);
                ctx.stroke();
            }
        }
    }
}

6. 鼠标交互实现

添加鼠标移动事件,使粒子对鼠标位置产生反应:

let mouseX = null;
let mouseY = null;

canvas.addEventListener('mousemove', (event) => {
    const rect = canvas.getBoundingClientRect();
    mouseX = event.clientX - rect.left;
    mouseY = event.clientY - rect.top;
});

canvas.addEventListener('mouseout', () => {
    mouseX = null;
    mouseY = null;
});

完整代码实现

下面是完整的JavaScript实现代码:

// 初始化Canvas
const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 500;

// 调整Canvas大小为窗口大小
function resizeCanvas() {
    canvas.width = window.innerWidth * 0.8;
    canvas.height = window.innerHeight * 0.7;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();

// 粒子构造函数
function Particle(x, y) {
    this.x = x;
    this.y = y;
    this.size = Math.random() * 5 + 1;
    this.speedX = Math.random() * 3 - 1.5;
    this.speedY = Math.random() * 3 - 1.5;
    this.color = `hsl(${Math.random() * 360}, 50%, 50%)`;
}

// 粒子更新方法
Particle.prototype.update = function() {
    this.x += this.speedX;
    this.y += this.speedY;
    
    // 边界检测与反弹
    if (this.x > canvas.width || this.x  canvas.height || this.y < 0) {
        this.speedY = -this.speedY;
    }
    
    // 鼠标交互
    if (mouseX !== null && mouseY !== null) {
        const dx = this.x - mouseX;
        const dy = this.y - mouseY;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        if (distance < 100) {
            // 鼠标附近的粒子受到排斥力
            this.speedX += dx / distance * 0.1;
            this.speedY += dy / distance * 0.1;
        }
    }
};

// 粒子绘制方法
Particle.prototype.draw = function() {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
    ctx.fill();
};

// 初始化粒子数组
let particles = [];
function initParticles(count) {
    particles = [];
    for (let i = 0; i < count; i++) {
        const x = Math.random() * canvas.width;
        const y = Math.random() * canvas.height;
        particles.push(new Particle(x, y));
    }
}

// 连接相近的粒子
function connectParticles() {
    for (let i = 0; i < particles.length; i++) {
        for (let j = i; j < particles.length; j++) {
            const dx = particles[i].x - particles[j].x;
            const dy = particles[i].y - particles[j].y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            if (distance  {
    const rect = canvas.getBoundingClientRect();
    mouseX = event.clientX - rect.left;
    mouseY = event.clientY - rect.top;
});

canvas.addEventListener('mouseout', () => {
    mouseX = null;
    mouseY = null;
});

// 动画循环
function animate() {
    ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    for (let i = 0; i  {
    const count = document.getElementById('particleCount').value;
    initParticles(count);
});

document.getElementById('particleCount').addEventListener('input', (e) => {
    document.getElementById('countDisplay').textContent = e.target.value;
});

性能优化建议

  1. 使用离屏Canvas进行预渲染静态元素
  2. 减少不必要的粒子间距离计算(使用空间分割算法)
  3. 合理控制粒子数量和连线距离阈值
  4. 使用requestAnimationFrame而不是setInterval
  5. 在页面不可见时暂停动画

扩展应用

此技术可以扩展应用于:

  • 网站背景特效
  • 数据可视化中的节点关系图
  • 游戏中的特效系统
  • 交互式艺术展示

// 完整的JavaScript实现代码将在这里执行
// 初始化Canvas
const canvas = document.getElementById(‘particleCanvas’);
const ctx = canvas.getContext(‘2d’);
canvas.width = 800;
canvas.height = 500;

// 调整Canvas大小为窗口大小
function resizeCanvas() {
canvas.width = window.innerWidth * 0.8;
canvas.height = window.innerHeight * 0.7;
}
window.addEventListener(‘resize’, resizeCanvas);
resizeCanvas();

// 粒子构造函数
function Particle(x, y) {
this.x = x;
this.y = y;
this.size = Math.random() * 5 + 1;
this.speedX = Math.random() * 3 – 1.5;
this.speedY = Math.random() * 3 – 1.5;
this.color = `hsl(${Math.random() * 360}, 50%, 50%)`;
}

// 粒子更新方法
Particle.prototype.update = function() {
this.x += this.speedX;
this.y += this.speedY;

// 边界检测与反弹
if (this.x > canvas.width || this.x canvas.height || this.y < 0) {
this.speedY = -this.speedY;
}

// 鼠标交互
if (mouseX !== null && mouseY !== null) {
const dx = this.x – mouseX;
const dy = this.y – mouseY;
const distance = Math.sqrt(dx * dx + dy * dy);

if (distance < 100) {
// 鼠标附近的粒子受到排斥力
this.speedX += dx / distance * 0.1;
this.speedY += dy / distance * 0.1;
}
}
};

// 粒子绘制方法
Particle.prototype.draw = function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
};

// 初始化粒子数组
let particles = [];
function initParticles(count) {
particles = [];
for (let i = 0; i < count; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
particles.push(new Particle(x, y));
}
}

// 连接相近的粒子
function connectParticles() {
for (let i = 0; i < particles.length; i++) {
for (let j = i; j < particles.length; j++) {
const dx = particles[i].x – particles[j].x;
const dy = particles[i].y – particles[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);

if (distance {
const rect = canvas.getBoundingClientRect();
mouseX = event.clientX – rect.left;
mouseY = event.clientY – rect.top;
});

canvas.addEventListener(‘mouseout’, () => {
mouseX = null;
mouseY = null;
});

// 动画循环
function animate() {
ctx.fillStyle = ‘rgba(0, 0, 0, 0.05)’;
ctx.fillRect(0, 0, canvas.width, canvas.height);

for (let i = 0; i {
const count = document.getElementById(‘particleCount’).value;
initParticles(count);
});

document.getElementById(‘particleCount’).addEventListener(‘input’, (e) => {
document.getElementById(‘countDisplay’).textContent = e.target.value;
});

HTML5 Canvas交互式粒子动画实现教程 - 前端图形技术
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 html HTML5 Canvas交互式粒子动画实现教程 – 前端图形技术 https://www.taomawang.com/web/html/1092.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务