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

求助:修复JavaScript和CSS模拟割草动画的速度异常与位置跟踪失效问题

求助:修复JavaScript和CSS模拟割草动画的速度异常与位置跟踪失效问题

我来帮你排查这个割草动画的问题哈!你遇到的速度跳变、位置跟踪不准的核心问题出在progress变量的计算逻辑上,另外关于草条的实现方式,我也给你一些优化建议~

一、核心问题:进度计算逻辑搞反了

你原来的progress计算式(viewportHeight / mowerPosition) * 10有两个明显的问题:

  • 当割草机在屏幕顶部时(mowerPosition数值很小),这个计算会得出一个超大的百分比,直接把整个草条瞬间变成浅色,看起来动画“跳变”而不是跟随割草机移动
  • 逻辑完全搞反:我们需要的是割草机下方的区域占草条的比例,而不是用视口高度除以割草机位置

正确的进度计算应该是这样的:

const progress = Math.min((mowerPosition / viewportHeight) * 100, 100);

这里的逻辑是:用割草机距离视口顶部的距离,除以整个视口的高度,得到割草机在屏幕中的垂直占比,转成百分比后,用Math.min确保数值不超过100%(避免割草机超出屏幕时出现异常)。

另外,你的渐变写法也可以优化——不需要用repeating-linear-gradient,普通的linear-gradient就能实现“上方深色、割草机下方浅色”的效果:

strip.style.background = `linear-gradient(to bottom, ${darkGreen} ${progress}%, ${lightGreen} ${progress}%)`;

这样设置后,渐变会在progress百分比的位置精准切换颜色,完全跟随割草机的位置变化。

二、割草机位置跟踪的细节优化

你用getBoundingClientRect().top获取割草机位置的思路是对的,但要注意处理边界情况:比如割草机刚进入屏幕(top为0)或者完全离开屏幕(top超过视口高度),用Math.min和Math.max把进度限制在0-100之间,避免出现负数或超出范围的数值。

三、草条实现方式的优化

你当前只创建了一个居中的草条,刚好匹配割草机的宽度,这个思路是没问题的。如果之后你想让整个草坪都能被割草机“修剪”,可以循环创建多个草条铺满整个屏幕宽度;如果只是做单路径的修剪效果,当前的单草条就足够用啦~

修正后的完整代码

JavaScript

const grass = document.getElementById('grass');
const lawnMower = document.getElementById('lawnMower');

// Function to create a vertical strip of grass that transitions color
function createGrassStrip(x, width) {
  const strip = document.createElement('div');
  strip.style.position = 'absolute';
  strip.style.top = '0';
  strip.style.left = `${x}px`;
  strip.style.width = `${width}px`;
  strip.style.height = '100%';
  // 初始颜色和草地区域保持一致
  strip.style.backgroundColor = '#388E3C';
  grass.appendChild(strip);
  return strip;
}

// Function to update the grass strip color based on lawn mower position
function updateGrassStrip(strip, mowerPosition) {
  const viewportHeight = window.innerHeight;
  // 修正进度计算逻辑,限制在0-100%之间
  const progress = Math.min(Math.max((mowerPosition / viewportHeight) * 100, 0), 100);

  // Transition from dark green to light green BELOW the lawn mower
  const darkGreen = '#388E3C';
  const lightGreen = '#8BC34A';
  strip.style.background = `linear-gradient(to bottom, ${darkGreen} ${progress}%, ${lightGreen} ${progress}%)`;
}

// Create a grass strip for the lawn mower's path
const mowerWidth = 100; // Width of the lawn mower
const mowerX = (window.innerWidth - mowerWidth) / 2; // Center the strip
const grassStrip = createGrassStrip(mowerX, mowerWidth);

// Update grass strip color on every animation frame
function animate() {
  const mowerPosition = lawnMower.getBoundingClientRect().top;
  updateGrassStrip(grassStrip, mowerPosition);
  requestAnimationFrame(animate);
}

// Start the animation
animate();

CSS

body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  font-family: Arial, sans-serif;
}

.lawn {
  position: relative;
  width: 100%;
  height: 100vh;
  background-color: #4CAF50;
  overflow: hidden;
}

.grass {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #388E3C;
}

.lawn-mower {
  position: absolute;
  top: 0;
  left: 50%;
  width: 100px;
  height: 50px;
  background-color: #FF5722;
  border-radius: 10px;
  transform: translateX(-50%);
  animation: mow 2.5s linear;
}

@keyframes mow {
  0% {
    top: 0;
  }

  100% {
    top: 100%;
  }
}

.content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  color: white;
  z-index: 1;
}

HTML

<div class="lawn">
  <div class="grass" id="grass"></div>
  <div class="lawn-mower" id="lawnMower"></div>
</div>
<div class="content">
</div>

这样修改之后,草条的颜色变化会精准跟随割草机的移动,动画速度和割草机的移动完全同步,不会再出现跳变或速度异常的情况啦~

备注:内容来源于stack exchange,提问作者1597jony

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:53:04