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

实现进度条从当前位置反向重置至0%的技术问题

问题:点击Reset按钮时进度条无法从当前位置反向回到0%

点击Reset按钮时,想要进度条从当前位置平滑反向滚动到0%,但现在一点Reset,进度条会先跳到100%再开始往回走,这明显不对。

修正后的完整代码

index.html

<!DOCTYPE html>
<html>

<head>
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

  <title>Loader Demo</title>
  <link rel="stylesheet" href="style.css">
 <link rel="icon" type="image/png" href="favicon.png">
   
</head>

<body>
  <div id="container">
      <div id="loader">
        <div class="bar"></div>
      </div> 
      <div id="bReset">
        <input type="submit" id="reset-button" name="reset-button" value="Reset">
       <!-- <input type="submit" id="pause-button" name="pause-button" value="Pause"> -->
        <input type="submit" id="start-button" name="start-button" value="Start">
      </div>
    </div>
 <script src="script.js"></script>

</body>

</html>

style.css

#container {
        display: flex;
        flex-direction: column;
        align-items: center;
      }
      #loader {
        width: 300px;
        height: 20px;
        border: 1px solid #ddd;
        border-radius: 4px;
        overflow: hidden;
      }
      /* 用CSS变量动态设置反向动画的起始宽度 */
      @keyframes progress-reverse {
  from { width: var(--current-width, 100%); }
  to { width: 0%; }
}
      #loader .bar {
        height: 100%;
        background-color: #007bff;
        animation: none;
        width: 0%;
        /* 初始化CSS变量 */
        --current-width: 0%;
      }
      #reset-button {
        border: none;
        background-color:  #007bff;
        color: white;
        padding: 5px 15px;
        font-size: 14px;
        border-radius: 4px;
        cursor: pointer;
        margin-top: 5px;
        width: 65px;
      }
      #start-button {
        border: none;
        background-color:  #007bff;
        color: white;
        padding: 5px 15px;
        font-size: 14px;
        border-radius: 4px;
        cursor: pointer;
        margin-top: 5px;
        width: 65px;
      }
      @keyframes progress {
        0% {width: 0%; background: #A1F5FF;}
        100% {width: 100%; background: #007bff;}
      }

script.js

const sb = document.querySelector('#start-button');
const rb = document.querySelector('#reset-button');
const pBar = document.querySelector('.bar');
const loaderWidth = 300; // 和CSS里#loader的width保持一致

let isPaused = false;

sb.addEventListener('click', () => {
  if (!isPaused) {
    sb.value = 'Pause';
    // 清除反向动画,重置状态
    pBar.style.animation = 'none';
    // 强制浏览器重绘,避免动画状态冲突
    void pBar.offsetWidth;
    pBar.style.animation = 'progress 3s linear infinite';
    pBar.style.animationPlayState = 'running';
  } else {
    sb.value = 'Start';
    pBar.style.animationPlayState = 'paused';
  }
  isPaused = !isPaused;
});

rb.addEventListener('click', () => {
  isPaused = false;
  sb.value = 'Start';
  // 先暂停当前的正向动画
  pBar.style.animationPlayState = 'paused';
  
  // 计算当前进度条的宽度百分比
  const computedStyle = window.getComputedStyle(pBar);
  const barWidthPx = parseFloat(computedStyle.getPropertyValue('width'));
  const currentWidthPercent = (barWidthPx / loaderWidth) * 100;
  
  // 设置CSS变量,让反向动画从当前宽度开始
  pBar.style.setProperty('--current-width', `${currentWidthPercent}%`);
  
  // 清除之前的动画,强制重绘,防止跳变
  pBar.style.animation = 'none';
  void pBar.offsetWidth;
  
  // 计算反向动画的时长:正向3秒走100%,所以按比例算时长
  const reverseDuration = (currentWidthPercent / 100) * 3;
  // 应用反向动画,forwards让动画结束后停在0%的状态
  pBar.style.animation = `progress-reverse ${reverseDuration}s linear forwards`;
});

关键修复点

  1. 动态反向动画起点:用CSS变量--current-width代替固定的100%起始值,让反向动画能从进度条当前的宽度开始。
  2. 强制重绘解决跳变:切换动画前先设animation: none,再用void pBar.offsetWidth触发重绘,避免浏览器复用之前的动画状态导致的跳100%问题。
  3. 匹配反向速度:根据当前进度计算反向动画的时长,保证反向滚动的速度和正向一致。
  4. 状态重置:点击Reset后把Start按钮改回初始状态,避免后续操作混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:37:40