You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JavaScript实现多雨滴下落效果遇问题:代码仅执行一次求排查

多雨滴下落效果的问题排查与修复

原代码的核心问题

  • 全局共享状态导致同步运动:所有雨滴共用同一个yPosition变量,会让所有雨滴同步移动,无法实现独立下落的效果;重置位置时还错误地操作了整个DOM集合的样式。
  • 定时器滥用导致逻辑混乱:在Raining函数内部重复调用setInterval(Raining, 40),每次触发都会生成新的定时器,短时间内会堆积大量重复定时器,不仅性能爆炸,还会让运动逻辑彻底混乱。
  • DOM元素操作错误:rain = document.querySelectorAll('div')会选中页面初始的.rain元素,而且Raining里直接操作rain.style.top——但rain是DOM元素集合,不是单个元素,这会直接报错。
  • 重复触发初始化逻辑:循环给每个雨滴调用Raining(),进一步加剧了定时器泛滥的问题。

修复后的完整代码

HTML

<div class="rain"></div>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  overflow: hidden;
  height: 100vh;
  background-color: #1a1a2e; /* 加深色背景让雨滴更明显 */
}

.rain-drop {
  position: absolute;
  top: 0;
  background-color: royalblue;
  width: 3px;
  height: 20px;
}

JavaScript

// 可调整的参数
const RAIN_COUNT = 20;
const MAX_FALL_SPEED = 3;
const MIN_FALL_SPEED = 1;

// 创建雨滴元素并初始化独立状态
function createRaindrops() {
  const body = document.querySelector('body');
  for (let i = 0; i < RAIN_COUNT; i++) {
    const drop = document.createElement('div');
    drop.classList.add('rain-drop');
    
    // 随机水平位置(百分比)
    const randomX = Math.random() * 100;
    drop.style.left = `${randomX}%`;
    
    // 随机初始垂直位置(让雨滴一开始分布在不同高度)
    const randomY = -Math.random() * window.innerHeight;
    drop.dataset.y = randomY;
    
    // 随机下落速度
    const randomSpeed = Math.random() * (MAX_FALL_SPEED - MIN_FALL_SPEED) + MIN_FALL_SPEED;
    drop.dataset.speed = randomSpeed;
    
    body.appendChild(drop);
  }
}

// 统一更新所有雨滴的位置
function updateRaindrops() {
  const raindrops = document.querySelectorAll('.rain-drop');
  const windowHeight = window.innerHeight;
  
  raindrops.forEach(drop => {
    let currentY = parseFloat(drop.dataset.y);
    const speed = parseFloat(drop.dataset.speed);
    
    currentY += speed;
    
    // 雨滴超出屏幕底部后,重置到顶部随机位置
    if (currentY > windowHeight) {
      currentY = -20; // 让雨滴完全从顶部进入视野
      drop.style.left = `${Math.random() * 100}%`; // 重置水平位置,模拟真实降雨的随机性
    }
    
    drop.dataset.y = currentY;
    drop.style.top = `${currentY}px`;
  });
}

// 启动降雨动画
createRaindrops();
setInterval(updateRaindrops, 40);

修复说明

  • 独立状态管理:每个雨滴通过dataset存储自己的垂直位置和下落速度,实现完全独立的运动轨迹。
  • 单一定时器驱动:只创建一个全局定时器,统一更新所有雨滴的位置,彻底避免定时器泛滥的问题。
  • 更自然的降雨效果:初始化时随机设置雨滴的初始高度和下落速度,重置时也随机水平位置,模拟真实降雨的无序感。
  • 精准DOM操作:用.rain-drop类名标记雨滴元素,避免误选页面其他div,确保样式操作只作用在目标元素上。

内容的提问来源于stack exchange,提问作者Wojtek1911

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:15:36