用JavaScript控制雪花位置、速度和透明度,结合requestAnimationFrame实现流畅下雪效果;雨滴需模拟斜向拖尾与溅射反馈;需校准时间戳应对移动端RAF节流。

用 CSS + JavaScript 实现轻量级下雪效果
纯 CSS 无法生成真实物理运动的雪花,必须靠 JS 控制位置、大小、飘落速度和透明度变化。主流做法是动态创建 <div> 元素作为雪花,用 <code>requestAnimationFrame 驱动动画,避免 setInterval 带来的卡顿或掉帧。
- 每片雪花是一个绝对定位的
<div>,初始 <code>top: -10px,随机left值 - 用
Math.random()控制大小(width/height在 2–6px)、不透明度(0.5–1)、水平偏移幅度(模拟风) - 关键:重置逻辑不能只看
top > window.innerHeight,还要考虑滚动——应以getBoundingClientRect().bottom 判定是否离开视口 - 性能敏感:建议限制最大雪花数(如 80–120),超出时用
removeChild()清理已移出的节点,而非隐藏(display: none仍占 DOM) - 透明度要渐变:入场时
opacity: 0.3→ 中段0.8→ 消失前0,否则像硬编码的直线 - 碰撞地面反馈缺失:若页面有 footer 或固定高度容器,雨滴到底部后应加个微小的「溅射」缩放动画(
transform: scale(0.8)后立刻重置),否则显得悬浮
下雨效果比下雪更难做对的三个点
雨滴视觉上是斜线快速下坠,但直接用 CSS transform: skewY() 或倾斜 div 会导致边缘锯齿且难以控制密度;真正可用的方案是 SVG 线段或 canvas 绘制,但最简方案仍是 JS + <div> 模拟。<ul>
<li>雨滴需带「拖尾」感:不能只改 <code>top,要同时更新 left(模拟风速),例如 left += wind * speed
兼容性陷阱:移动端 touchstart 会中断 requestAnimationFrame
在 iOS Safari 或部分安卓浏览器中,用户手指触碰屏幕瞬间,requestAnimationFrame 可能被暂停 100–300ms,导致雪花/雨滴「卡住一帧」。这不是 bug,而是浏览器为优化触摸响应做的主动节流。
- 解决方案不是换定时器,而是加一层「时间戳校准」:记录上一帧
timestamp,计算实际间隔,动态调整位移增量(deltaY = speed * (now - lastTime) / 16) - 禁用
touchmove默认行为会影响滑动,所以只在touchstart时临时设body.style.touchAction = 'none',动画帧结束后立刻恢复 - 测试重点:用真机开启「慢速网络」+「低电量模式」,这两者会加剧 RAF 调度延迟
直接可用的最小化代码片段(无依赖)
function createSnow() {
const snowflake = document.createElement('div');
snowflake.style.cssText = `
position: fixed;
top: -10px;
width: ${Math.random()*4+2}px;
height: ${snowflake.style.width};
background: #fff;
border-radius: 50%;
pointer-events: none;
opacity: ${Math.random()*0.5+0.5};
`;
document.body.appendChild(snowflake);
<p>let pos = Math.random() <em> window.innerWidth;
let speed = Math.random() </em> 2 + 1;
let wind = (Math.random() - 0.5) * 0.5;</p><p>function fall() {
const rect = snowflake.getBoundingClientRect();
if (rect.bottom < 0 || pos > window.innerWidth + 10 || pos < -10) {
snowflake.remove();
return;
}</p><pre class="brush:php;toolbar:false;">pos += wind;
snowflake.style.left = `${pos}px`;
snowflake.style.top = `${parseFloat(snowflake.style.top) + speed}px`;
requestAnimationFrame(fall);} fall(); }
// 启动:每 200ms 创建一片,共 100 片 for (let i = 0; i
这段代码没封装成类,不维护实例列表,靠 getBoundingClientRect() 和 remove() 自清理。如果页面有 sticky header 或 fixed navbar,记得把雪花父容器设为 document.documentElement 而非 document.body,否则会被遮挡。
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
立即学习“前端免费学习笔记(深入)”;


















