js实现雪花
使用 Canvas 绘制雪花
通过 HTML5 的 Canvas API 动态生成雪花效果,适合需要复杂动画的场景。
const canvas = document.getElementById('snowCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const flakes = [];
for (let i = 0; i < 100; i++) {
flakes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.random() * 3 + 1,
speed: Math.random() * 1 + 0.5,
opacity: Math.random() * 0.5 + 0.5
});
}
function drawFlakes() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
flakes.forEach(flake => {
ctx.beginPath();
ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
flake.y += flake.speed;
if (flake.y > canvas.height) {
flake.y = 0;
flake.x = Math.random() * canvas.width;
}
});
requestAnimationFrame(drawFlakes);
}
drawFlakes();
HTML 部分需要添加:
<canvas id="snowCanvas" style="position:fixed;top:0;left:0;z-index:999;pointer-events:none;"></canvas>
使用 CSS 动画实现
轻量级的纯 CSS 解决方案,适合简单场景:
.snowflake {
position: fixed;
color: #fff;
user-select: none;
pointer-events: none;
animation: fall linear infinite;
}
@keyframes fall {
to {
transform: translateY(100vh);
}
}
function createSnowflakes() {
const snowflake = document.createElement('div');
snowflake.classList.add('snowflake');
snowflake.innerHTML = '❄';
snowflake.style.left = Math.random() * window.innerWidth + 'px';
snowflake.style.animationDuration = Math.random() * 3 + 2 + 's';
snowflake.style.opacity = Math.random();
snowflake.style.fontSize = Math.random() * 10 + 10 + 'px';
document.body.appendChild(snowflake);
setTimeout(() => {
snowflake.remove();
}, 5000);
}
setInterval(createSnowflakes, 100);
使用 SVG 实现
矢量图形方案,适合需要缩放而不失真的场景:
const svgNS = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(svgNS, 'svg');
svg.style.position = 'fixed';
svg.style.top = '0';
svg.style.left = '0';
svg.style.width = '100%';
svg.style.height = '100%';
svg.style.pointerEvents = 'none';
document.body.appendChild(svg);
function createSVGSnow() {
const flake = document.createElementNS(svgNS, 'path');
const size = Math.random() * 10 + 5;
const x = Math.random() * window.innerWidth;
// 简化的雪花路径
flake.setAttribute('d', `
M${x},0
L${x-size/2},${size}
L${x+size},${size/3}
L${x-size},${size/3}
L${x+size/2},${size}
Z
`);
flake.setAttribute('fill', 'white');
flake.setAttribute('opacity', Math.random() * 0.7 + 0.3);
svg.appendChild(flake);
let y = 0;
const fall = setInterval(() => {
y += 1;
flake.setAttribute('transform', `translate(0,${y})`);
if (y > window.innerHeight) {
clearInterval(fall);
flake.remove();
}
}, 30);
}
setInterval(createSVGSnow, 200);
性能优化建议
- 对于大量雪花粒子,建议使用对象池模式重复利用DOM元素
- 移动端设备需要减少同时显示的雪花数量
- 使用
will-change: transform提升CSS动画性能 - 考虑使用WebGL(Three.js等库)实现超大规模雪景
所有方案都需要根据实际需求调整参数,如雪花数量、下落速度、大小变化等参数来达到最佳视觉效果。







