上一篇
爱心飘落动态图js
- 行业动态
- 2025-05-05
- 2712
使用HTML5 Canvas结合JS实现,通过随机生成爱心坐标与下落轨迹,利用requestAnimationFrame逐帧绘制飘落动画,可添加重力加速度与旋转效果增强真实感
实现原理
通过HTML5 Canvas绘制多个爱心图形,利用JavaScript控制爱心的下落轨迹、速度、旋转等属性,结合requestAnimationFrame
实现平滑动画效果。
完整代码示例
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8">爱心飘落动画</title> <style> body { margin: 0; background: #222; overflow: hidden; } canvas { display: block; } </style> </head> <body> <canvas id="heartCanvas"></canvas> <script> // 获取Canvas元素 const canvas = document.getElementById('heartCanvas'); const ctx = canvas.getContext('2d'); // 设置Canvas尺寸 canvas.width = window.innerWidth; canvas.height = window.innerHeight; // 监听窗口大小变化 window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); // 定义爱心数量 const heartCount = 100; // 存储所有爱心对象 const hearts = []; // 生成随机数工具函数 const random = (min, max) => Math.random() (max min) + min; // 初始化爱心数组 for (let i = 0; i < heartCount; i++) { hearts.push(createHeart()); } // 创建单个爱心对象 function createHeart() { return { x: random(0, canvas.width), // 初始X坐标 y: random(-200, -50), // 初始Y坐标(画布外) size: random(8, 15), // 爱心大小 speed: random(1, 3), // 下落速度 rotate: random(0, Math.PI 2), // 初始旋转角度 alpha: random(0.5, 1) // 透明度 }; } // 绘制单个爱心 function drawHeart(heart) { ctx.save(); ctx.fillStyle = `rgba(255, 105, 180, ${heart.alpha})`; // 粉色半透明 ctx.translate(heart.x, heart.y); ctx.rotate(heart.rotate); ctx.fillStyle = `rgba(255, 105, 180, ${heart.alpha})`; drawHeartShape(heart.size); ctx.restore(); } // 绘制心形路径 function drawHeartShape(size) { ctx.beginPath(); ctx.moveTo(0, -size / 2); // 顶部尖点 ctx.bezierCurveTo(size, -size, size, size / 2, 0, size / 2); // 右半边 ctx.bezierCurveTo(-size, size / 2, -size, -size, 0, -size / 2); // 左半边 ctx.closePath(); ctx.fill(); } // 更新爱心状态 function updateHearts() { hearts.forEach(heart => { heart.y += heart.speed; // 下落 heart.rotate += 0.01; // 缓慢旋转 // 超出底部后重置位置 if (heart.y > canvas.height) { heart.y = random(-200, -50); heart.x = random(0, canvas.width); heart.size = random(8, 15); heart.speed = random(1, 3); heart.rotate = random(0, Math.PI 2); } }); } // 渲染动画帧 function render() { ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布 hearts.forEach(drawHeart); // 绘制所有爱心 updateHearts(); // 更新状态 requestAnimationFrame(render); // 循环调用 } // 启动动画 render(); </script> </body> </html>
参数说明表
参数名称 | 作用 | 默认值范围 | 调整建议 |
---|---|---|---|
heartCount | 爱心数量 | 50-200 | 数值越大越密集,性能消耗越高 |
size | 单个爱心大小 | 8-15 | 增大可突出视觉效果,但过多大爱心可能显乱 |
speed | 下落速度 | 1-3 | 数值越大下落越快,可配合风力效果调整 |
alpha | 透明度 | 5-1 | 降低透明度可营造柔和感 |
注意事项
- 性能优化:当爱心数量超过200时,低配置设备可能出现卡顿,建议通过
requestAnimationFrame
替代setInterval
保证流畅度。 - 移动端适配:需测试触摸设备效果,可适当减少爱心数量(如50-100)。
- 颜色自定义:修改
ctx.fillStyle
中RGBA值即可调整颜色(如红色rgba(255,50,50,0.8)
)。 - 背景兼容:若页面有复杂背景,建议给Canvas添加
backgroundColor
属性或调整爱心颜色对比度。
相关问题与解答
问题1:如何让爱心呈现不同颜色?
解答:在createHeart
函数中为每个爱心随机生成颜色值,
function createHeart() { return { // ...其他属性 color: `hsla(${Math.random() 360}, 70%, 50%, ${random(0.5, 1)})` }; }
然后在drawHeart
函数中使用heart.color
替代固定颜色。
问题2:如何让爱心在鼠标悬停时暂停下落?
解答:监听mouseenter
和mouseleave
事件,通过标志位控制动画更新:
let isPaused = false; canvas.addEventListener('mouseenter', () => isPaused = true); canvas.addEventListener('mouseleave', () => isPaused = false); function updateHearts() { if (isPaused) return; // 暂停更新 hearts.forEach(heart => { // ...原有逻辑 }); }