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

JavaScript如何选中列表中的单个子元素?雪花动画问题求助

雪花飘落重置位置问题解决方案

问题根源

  • 仅选中第一个雪花:document.querySelector('.snow')只会返回DOM中第一个带snow类的元素,所以你的代码始终只操作第一个雪花,其他雪花完全没被处理。
  • 定时与动画时长不匹配:固定6秒的setInterval和每个雪花的动画时长(6s、8s、12s等)不一致,只有第一个雪花的6秒动画时长刚好和定时对齐,才出现了“巧合生效”的情况。

修复方案

核心思路是监听每个雪花的动画结束事件,当雪花完成一次飘落(到达视口底部)时,随机重置它的水平位置,这样每个雪花都会独立触发位置更新,完全匹配各自的动画时长。

修改后的JavaScript代码

// 获取所有雪花元素
const allSnowflakes = document.querySelectorAll('.snow');

// 定义重置位置的函数,接收单个雪花元素作为参数
function resetSnowflakePosition(snowflake) {
  const randomPosition = Math.random() * 101; // 0-100%的随机值
  snowflake.style.left = `${randomPosition}%`;
}

// 给每个雪花绑定动画结束事件
allSnowflakes.forEach(snowflake => {
  snowflake.addEventListener('animationend', () => {
    resetSnowflakePosition(snowflake);
  });
});

补充说明

  • 移除了原来的setInterval,改用animationend事件,完全贴合每个雪花的飘落周期,不会出现时间错位。
  • 用querySelectorAll获取所有雪花,通过forEach遍历给每个雪花绑定事件,确保每个雪花都能被独立控制。
  • 重置位置的函数现在接收单个雪花元素作为参数,精准操作目标元素。

可选优化(雪花效果更自然)

如果想让雪花效果更真实,可以在初始化时给每个雪花随机设置大小和飘落速度:

allSnowflakes.forEach(snowflake => {
  // 随机大小:5-15px
  const size = Math.random() * 10 + 5;
  snowflake.style.width = `${size}px`;
  snowflake.style.height = `${size}px`;
  
  // 随机动画时长:4-12秒
  const duration = Math.random() * 8 + 4;
  snowflake.style.animationDuration = `${duration}s`;
  
  // 绑定动画结束事件
  snowflake.addEventListener('animationend', () => {
    resetSnowflakePosition(snowflake);
  });
});

同时可以移除CSS中针对nth-child的硬编码样式,让随机效果完全由JS控制。

完整代码示例

HTML(无需修改)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="stylesheet.css">
        <title>Matching Game Project</title>
    </head>
    <body id="body">
        <header id="header">Matching Game</header>
        <div class="snowfall">
            <div class="snow"></div>
            <div class="snow"></div>
            <div class="snow"></div>
            <div class="snow"></div>
            <div class="snow"></div>
        </div>
        <script src="snow.js"></script>
    </body>
</html>

CSS(移除硬编码的nth-child样式)

body {
    margin: 0;
    background: linear-gradient(snow, skyblue);
    background-attachment: fixed;
}

#header {
    margin-top: 5px;
    text-align: center;
    font-family: sans-serif;
    font-size: 40px;
    color: white;
    -webkit-text-stroke-color: black;
    -webkit-text-stroke-width: 0.8px;
    text-shadow: 0px 0px 5px black;
    width: 100vw;
    height: 5vh;
    background-color: snow;
    border-bottom: 3px solid black;
    z-index: 999;
}

/*-----Snow-----*/

.snowfall {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.snow {
    background-color: white;
    height: 10px;
    width: 10px;
    border-radius: 50%;
    border: 1px solid black;
    animation: fall linear infinite;
    position: absolute;
    top: -40px;
    left: 10%;
    z-index: 1;
}

@keyframes fall{
    0% {
        transform: translateY(0);
    }
    100% {
        transform: translateY(110vh);
    }
}

JavaScript(带随机优化版本)

const allSnowflakes = document.querySelectorAll('.snow');

function resetSnowflakePosition(snowflake) {
  const randomPosition = Math.random() * 101;
  snowflake.style.left = `${randomPosition}%`;
}

allSnowflakes.forEach(snowflake => {
  // 随机大小
  const size = Math.random() * 10 + 5;
  snowflake.style.width = `${size}px`;
  snowflake.style.height = `${size}px`;
  
  // 随机飘落时长
  const duration = Math.random() * 8 + 4;
  snowflake.style.animationDuration = `${duration}s`;
  
  // 动画结束后重置位置
  snowflake.addEventListener('animationend', () => {
    resetSnowflakePosition(snowflake);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 20:13:19