用HTML5 Canvas和CSS3动画,给你的个人网站加个新年许愿孔明灯特效(附完整源码)
·
用HTML5 Canvas和CSS3动画打造可定制的许愿孔明灯特效
春节将至,为个人网站添加节日氛围是提升用户体验的好方法。本文将带你从零开始实现一个轻量级、可定制的许愿孔明灯特效,不仅适合前端初学者理解动画原理,也能满足个人站长快速集成的需求。
1. 特效设计思路与核心架构
这个许愿孔明灯特效的核心在于模块化设计和参数可配置。我们将其拆分为三个独立组件:
- 星空背景层:使用CSS3渐变和动画创建闪烁的星空效果
- 孔明灯动画层:通过Canvas绘制可交互的孔明灯群
- 祝福语交互层:实现点击孔明灯显示随机祝福语的功能
// 模块化结构示意
const wishLantern = {
config: {}, // 可配置参数
init(), // 初始化
render(), // 渲染主循环
events: {} // 交互事件处理
};
这种设计让特效可以轻松嵌入任何网页,只需调整配置参数就能适应不同布局。
2. 实现星空背景与孔明灯基础动画
我们先创建基础的HTML结构,注意使用position: fixed确保特效全屏显示:
<div class="wish-lantern-effect">
<canvas id="lantern-canvas"></canvas>
<div class="wish-message"></div>
</div>
CSS部分实现星空背景的关键代码:
.wish-lantern-effect {
position: fixed;
top: 0; left: 0;
width: 100vw; height: 100vh;
background: radial-gradient(
ellipse at bottom,
#1B2735 0%,
#090A0F 100%
);
overflow: hidden;
z-index: 9999;
pointer-events: none;
}
.star {
position: absolute;
background: white;
border-radius: 50%;
animation: twinkle var(--duration) infinite alternate;
}
@keyframes twinkle {
0% { opacity: 0.3; }
100% { opacity: 0.8; }
}
3. Canvas绘制可交互孔明灯
使用Canvas而非DOM元素绘制孔明灯,性能更优且更灵活。每个孔明灯是一个对象实例:
class Lantern {
constructor(ctx) {
this.ctx = ctx;
this.x = Math.random() * canvas.width;
this.y = canvas.height + 50;
this.speed = 1 + Math.random() * 2;
this.size = 30 + Math.random() * 20;
this.color = `hsl(${20 + Math.random() * 20}, 100%, 50%)`;
this.wish = wishes[Math.floor(Math.random() * wishes.length)];
}
draw() {
const {ctx, x, y, size, color} = this;
ctx.save();
ctx.beginPath();
// 绘制灯笼主体
ctx.fillStyle = color;
ctx.shadowColor = color;
ctx.shadowBlur = 15;
ctx.moveTo(x, y);
ctx.arc(x, y, size/2, 0, Math.PI * 2);
ctx.fill();
// 绘制灯笼骨架线
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.lineWidth = 1;
for(let i=0; i<8; i++) {
const angle = Math.PI/4 * i;
ctx.moveTo(x, y);
ctx.lineTo(
x + Math.cos(angle) * size/2,
y + Math.sin(angle) * size/2
);
}
ctx.stroke();
ctx.restore();
}
update() {
this.y -= this.speed;
if(this.y < -50) this.reset();
}
reset() {
this.y = canvas.height + 50;
this.x = Math.random() * canvas.width;
}
}
4. 添加点击交互与祝福语显示
为孔明灯添加点击交互需要解决两个问题:
- Canvas元素的点击检测
- 祝福语的动画显示
// 点击检测实现
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
lanterns.forEach(lantern => {
const distance = Math.sqrt(
Math.pow(x - lantern.x, 2) +
Math.pow(y - lantern.y, 2)
);
if(distance < lantern.size/2) {
showWish(lantern.wish, x, y);
}
});
});
// 祝福语显示函数
function showWish(text, x, y) {
const wishEl = document.createElement('div');
wishEl.className = 'wish-bubble';
wishEl.textContent = text;
wishEl.style.left = `${x}px`;
wishEl.style.top = `${y}px`;
document.body.appendChild(wishEl);
anime({
targets: wishEl,
translateY: -100,
opacity: [0, 1],
duration: 800,
easing: 'easeOutQuad',
complete: () => {
setTimeout(() => {
wishEl.remove();
}, 2000);
}
});
}
5. 参数配置与性能优化
为了让特效适应不同场景,我们提供以下可配置参数:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| density | number | 0.5 | 孔明灯密度 (0-1) |
| speed | number | 1 | 上升速度基数 |
| size | object | {min:30,max:50} | 孔明灯尺寸范围 |
| colors | array | ['#ff8c00','#ff4500'] | 颜色主题 |
| interactive | boolean | true | 是否启用点击交互 |
性能优化技巧:
- 使用requestAnimationFrame节流:
let lastTime = 0;
const fps = 30;
const interval = 1000/fps;
function animate(timestamp) {
if(timestamp - lastTime > interval) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
lanterns.forEach(lantern => {
lantern.update();
lantern.draw();
});
lastTime = timestamp;
}
requestAnimationFrame(animate);
}
-
对象池技术:复用已移出屏幕的孔明灯对象,避免频繁创建销毁
-
离屏Canvas:对静态背景使用离屏缓存
6. 实际集成示例
将特效集成到网站只需三个步骤:
- 引入CSS和JS文件
<link rel="stylesheet" href="wish-lantern.css">
<script src="wish-lantern.js" defer></script>
- 添加容器元素
<div id="wish-lantern-container"></div>
- 初始化配置
document.addEventListener('DOMContentLoaded', () => {
wishLantern.init({
container: '#wish-lantern-container',
density: 0.7,
colors: ['#FFD700', '#FF6347'],
wishes: [
'心想事成',
'学业进步',
'事业有成',
'阖家幸福'
]
});
});
7. 进阶定制与创意扩展
对于想要进一步定制的开发者,可以考虑:
- 添加拖拽许愿功能:
let isDragging = false;
let customLantern = null;
canvas.addEventListener('mousedown', (e) => {
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
if(y > canvas.height - 100) {
isDragging = true;
customLantern = new Lantern(ctx);
customLantern.x = x;
customLantern.y = y;
}
});
canvas.addEventListener('mousemove', (e) => {
if(isDragging && customLantern) {
customLantern.x = e.clientX - rect.left;
customLantern.y = e.clientY - rect.top;
}
});
canvas.addEventListener('mouseup', () => {
if(isDragging && customLantern) {
customLantern.speed = 1;
lanterns.push(customLantern);
isDragging = false;
customLantern = null;
}
});
-
与后端API集成:将用户的许愿内容存储到数据库
-
添加音效:使用Web Audio API播放背景音乐和交互音效
完整项目代码已托管在GitHub,包含详细注释和多个预设主题,可直接下载使用或作为学习参考。实现过程中最有趣的部分是调试孔明灯的物理轨迹,让上升动画看起来更自然。
更多推荐
所有评论(0)