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

使用requestAnimationFrame实现物体跳跃异常问题求助

问题分析

你的代码核心问题在于同时触发了上升和下落两个动画,而且共用了同一个time对象,导致两个动画逻辑互相干扰:

  • jump()函数里同时调用requestAnimationFrame(moveup)和requestAnimationFrame(movedown),这两个回调会在同一帧(或极短时间内)执行。
  • 你紧接着把time.start=0,movedown执行时会把position计算为finalPosition*(1-0)=finalPosition,直接把物体放到最高处,覆盖了moveup的初始计算。
  • 之后只有movedown的逻辑在持续执行,所以看起来只有下落过程是平滑的。
修复方案

我们需要让两个动画顺序执行:等上升动画完全结束后,再启动下落动画。同时要避免共用状态导致的冲突,每个动画阶段单独管理时间状态。

修改后的完整代码:

let finalPosition = 200; // 假设最大高度是200px,你可以根据需求调整
const obj = document.getElementById('your-object'); // 替换成你的物体元素

// 上升动画函数
const moveup = (now) => {
  // 每个动画阶段单独初始化时间状态,避免共用冲突
  const time = { start: now, total: 500 };
  const animate = (currentNow) => {
    const elapsed = currentNow - time.start;
    const progress = Math.min(elapsed / time.total, 1); // 防止进度超过1
    // 使用缓动函数让上升更自然(可选,比如ease-out)
    const easedProgress = 1 - Math.pow(1 - progress, 3);
    const position = easedProgress * finalPosition;
    obj.style.bottom = `${position}px`;
    
    if (progress < 1) {
      requestAnimationFrame(animate);
    } else {
      // 上升结束后启动下落动画
      requestAnimationFrame(movedown);
    }
  };
  animate(now);
};

// 下落动画函数
const movedown = (now) => {
  const time = { start: now, total: 500 };
  const animate = (currentNow) => {
    const elapsed = currentNow - time.start;
    const progress = Math.min(elapsed / time.total, 1);
    // 缓动函数让下落更自然(可选,比如ease-in)
    const easedProgress = Math.pow(progress, 3);
    const position = finalPosition * (1 - easedProgress);
    obj.style.bottom = `${position}px`;
    
    if (progress < 1) {
      requestAnimationFrame(animate);
    }
  };
  animate(now);
};

function jump() {
  // 只启动上升动画,下落动画由上升动画结束后触发
  requestAnimationFrame(moveup);
}

document.addEventListener('keydown', jump, false);
关键修改点
  1. 动画顺序执行:在moveup的动画结束(progress >=1)时,才调用requestAnimationFrame(movedown),确保上升完成后再下落。
  2. 独立时间状态:每个动画函数内部创建自己的time对象,避免共用状态导致的冲突,不需要再手动重置time.start。
  3. 缓动函数优化(可选):添加了ease-out(上升)和ease-in(下落)的缓动计算,让跳跃更符合真实物理效果,你可以根据需求去掉或替换其他缓动公式。
  4. 进度边界处理:用Math.min(progress, 1)确保进度不会超过1,避免动画结束后位置出现异常。
额外说明

如果需要支持连续跳跃(比如用户按住按键多次触发),可以添加一个isJumping标志位,防止动画叠加:

let isJumping = false;

function jump() {
  if (!isJumping) {
    isJumping = true;
    requestAnimationFrame(moveup);
  }
}

// 在movedown的动画结束时重置标志位
const movedown = (now) => {
  // ... 原有代码
  if (progress < 1) {
    requestAnimationFrame(animate);
  } else {
    isJumping = false;
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:44:03