<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas碎纸片扩散动画特效</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background: linear-gradient(135deg, #1a1a2e, #16213e);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, sans-serif;
}
canvas {
display: block;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.content {
position: relative;
z-index: 2;
color: white;
text-align: center;
padding: 20px;
max-width: 600px;
}
h1 {
font-size: 3em;
margin-bottom: 20px;
text-shadow: 0 2px 10px rgba(0,0,0,0.5);
}
p {
font-size: 1.2em;
line-height: 1.6;
margin-bottom: 30px;
}
.btn {
display: inline-block;
padding: 12px 30px;
background: rgba(255,255,255,0.2);
color: white;
text-decoration: none;
border-radius: 30px;
font-size: 1.1em;
transition: all 0.3s ease;
border: 1px solid rgba(255,255,255,0.3);
}
.btn:hover {
background: rgba(255,255,255,0.3);
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
/* 插入的链接样式 */
.custom-link {
position: fixed;
bottom: 20px;
right: 20px;
color: rgba(255,255,255,0.7);
text-decoration: none;
font-size: 14px;
background: rgba(0,0,0,0.3);
padding: 8px 15px;
border-radius: 20px;
z-index: 10;
transition: all 0.3s ease;
}
.custom-link:hover {
color: white;
background: rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<canvas id="confetti"></canvas>
<div class="content">
<h1>碎纸片特效</h1>
<p>点击下方按钮触发彩色碎纸片扩散动画效果</p>
<a href="#" class="btn" id="triggerBtn">触发动画</a>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('confetti');
const ctx = canvas.getContext('2d');
const btn = document.getElementById('triggerBtn');
// 设置canvas尺寸为窗口大小
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 碎纸片数组
let confettiPieces = [];
// 颜色数组
const colors = [
'#ff9ff3', '#feca57', '#ff6b6b',
'#48dbfb', '#1dd1a1', '#f368e0',
'#ff9f43', '#ee5253', '#0abde3',
'#10ac84', '#00d2d3', '#5f27cd'
];
// 碎纸片类
class Confetti {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = Math.random() * 10 + 5;
this.color = colors[Math.floor(Math.random() * colors.length)];
this.rotation = Math.random() * Math.PI * 2;
this.rotationSpeed = Math.random() * 0.2 - 0.1;
this.speedX = Math.random() * 6 - 3;
this.speedY = Math.random() * -15 - 5;
this.gravity = 0.2;
this.alpha = 1;
this.fade = Math.random() * 0.05 + 0.01;
this.shape = Math.random() > 0.5 ? 'rect' : 'circle';
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += this.gravity;
this.rotation += this.rotationSpeed;
this.alpha -= this.fade;
return this.alpha > 0;
}
draw() {
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.fillStyle = this.color;
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
if (this.shape === 'rect') {
ctx.fillRect(-this.size/2, -this.size/2, this.size, this.size);
} else {
ctx.beginPath();
ctx.arc(0, 0, this.size/2, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
}
}
// 创建碎纸片
function createConfetti(x, y, count = 100) {
for (let i = 0; i < count; i++) {
confettiPieces.push(new Confetti(x, y));
}
}
// 动画循环
function animate() {
requestAnimationFrame(animate);
// 清除画布,使用半透明背景制造拖尾效果
ctx.fillStyle = 'rgba(26, 26, 46, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 更新和绘制所有碎纸片
confettiPieces = confettiPieces.filter(confetti => {
confetti.draw();
return confetti.update();
});
}
// 初始化动画
animate();
// 点击按钮触发动画
btn.addEventListener('click', function(e) {
e.preventDefault();
createConfetti(canvas.width / 2, canvas.height / 2, 150);
});
// 窗口大小改变时调整canvas尺寸
window.addEventListener('resize', function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
// 初始动画
setTimeout(() => {
createConfetti(canvas.width / 2, canvas.height / 2, 100);
}, 500);
});
</script>
</body>
</html>
Canvas碎纸片扩散动画特效
于 2025-06-16 15:35:14 首次发布