【问题标题】:How do I reset a JQueryUI effect animation?如何重置 JQueryUI 效果动画?
【发布时间】:2020-08-02 20:36:00
【问题描述】:

我有两个不同的计时器栏,每个栏的结束时间超过 5 秒。但是当我尝试停止并重置第一个计时器时,它不会重置,只会从停止的地方继续。

期望的行为: Timer1 启动 用户按键 Timer1 完成一半停止 定时器 2 启动 Timer2 到期 Timer1 重置为 100% 并启动

这是 timer1 的启动方式:

function StartTimer1(){       
 $("#timer-bar").show().width("100%");
    
$("#timer-bar").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function () {
                //do stuff
            }
        });
}

然后当有人敲键时,我就跑

 //Stop timer1
     $("#timer-bar").stop(true, false);

//Start timer2 
    $("#answer-timer-bar").hide({
        effect: "blind",
        easing: "linear",
        duration: 5000,
        direction: "left",
        complete: function () {
            //do stuff
        }
    });

然后在 timer2 到期后,我再次按下另一个调用 StartTimer1() 的键。即使我在开始动画之前将宽度重置为 100%,它仍然会从第一次停止的地方继续。我阅读了队列并认为这是我的答案,但我尝试为每个计时器选项添加唯一的队列名称,但每当我这样做时,计时器由于某种原因永远不会启动。当我将队列设置为true时也是如此。我在调用 Stop() 时尝试了 clearQueue 和 jumpToEnd 参数的不同选项,但似乎无法获得我想要的行为。

任何帮助将不胜感激。谢谢。

JSFiddle:https://jsfiddle.net/58rzg6w0/7

【问题讨论】:

    标签: javascript html jquery css jquery-ui-sortable


    【解决方案1】:

    隐藏和显示方法的动画?
    根据我的研究和this stackoverflow post 如果我们使用$(selector).animate() 而不是$(selector).hide()$(selector).show(),我们将对动画有更多的控制。

    在动画中使用容器元素
    我已经分离了 css 样式并为动画本身添加了叠加层,以防止容器折叠(如果元素为 display: none,则元素将没有高度)。这可能有用与否,这取决于您的目标。无论如何,您仍然可以隐藏它们,因此使用此方法没有缺点。将动画与容器分开可能会很有用。

    恢复动画的时间问题
    如果其中一个计时器在动画期间恰好停止并恢复,则动画仍将具有相同的持续时间“更短的距离”,从而导致动画速度变慢。

    但是,如果我们重置 timer1 的动画,就像您在示例中所做的那样,那么这不是问题,但否则,我们必须根据动画进度和总动画长度调整动画持续时间(您可以在下面的脚本中看到这一点)。

    只是为了好玩 - 显示时间
    通常,计时器会显示时间,因此我将动画的持续时间添加到叠加层上。这只是您可能想要添加的简单添加(加上样式)。动画的持续时间可以通过 data-duration(以毫秒为单位)在计时器元素上设置。

    $('document').ready(function() {
      ResetAll();
    });
    
    function TimeLeft(id, initialTime) {
      const $timer = $('#' + id);
      const $overlay = $timer.find('.overlay');
      const percentageToGo = (parseInt($overlay.css('width')) / parseInt($timer.css('width')));
      return percentageToGo * initialTime;
    }
    
    function StartTimer(id, onComplete = null) {
      const $timer = $('#' + id);
      const $overlay = $timer.find('.overlay');
      const duration = $timer.data('duration');
      const time = TimeLeft(id, duration);
      $overlay.animate({
        width: '0%'
      }, {
        duration: time,
        easing: 'linear',
        step: function() {
          $overlay.html(Math.round(TimeLeft(id, duration)) / 1000);
        },
        complete: function() {
          // $timer.css('display', 'none'); // remove all comments to hide the timer element completly
          $overlay.html('');
          if (onComplete && typeof onComplete === 'function') {
            onComplete();
          }
        }
      });
    }
    
    function StopTimer(id) {
      $('#' + id + ' .overlay').stop(true, false);
    }
    
    function ResetTimer(id) {
      const $timer = $('#' + id);
      const $overlay = $timer.find('.overlay');
      $overlay.stop(true).css('width', '100%');
      // $timer.css('display', 'block'); // remove all comments to hide the timer element completly
      $overlay.html(Math.round(TimeLeft(id, $timer.data('duration'))) / 1000);
    }
    
    function StopTimer1AndStartTimer2() {
      ResetTimer('timer1');
      ResetTimer('timer2');
      StartTimer('timer2', function() {
        // $('#timer2').css('display', 'none'); // remove all comments to hide the timer element completly
        StartTimer('timer1');
      });
    }
    
    function ResetAll() {
      ResetTimer('timer1');
      ResetTimer('timer2');
      // $('.timer').css('display', 'block'); // remove all comments to hide the timer element completly
    }
    .timer {
      position: relative;
      height: 30px;
      width: 100%;
      z-index: 1;
    }
    
    .overlay {
      color: white;
      position: absolute;
      width: 100%;
      top: 0;
      left: 0;
      bottom: 0;
      z-index: -1;
    }
    
    #timer1 .overlay {
      background-color: red;
    }
    
    #timer2 .overlay {
      background-color: blue;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
    <div id="timer1" data-duration="5000" class="timer">
      <div class="overlay"></div>
    </div>
    <div id="timer2" data-duration="3000" class="timer">
      <div class="overlay"></div>
    </div>
    <p>This first button is probably what you want, the rest is extra:</p>
    <button onclick="StopTimer1AndStartTimer2();">Stop Timer1 - Reset Timer1 - Start Timer2 - on complete Start Timer2</button>
    <button onclick="StartTimer('timer1');">Start/Resume Timer1</button>
    <button onclick="StartTimer('timer2');">Start/Resume Timer2</button>
    <button onclick="StartTimer('timer1'); StartTimer('timer2');">Start/Resume All</button>
    <button onclick="StopTimer('timer1');">Stop Timer1</button>
    <button onclick="StopTimer('timer2');">Stop Timer2</button>
    <button onclick="StopTimer('timer1'); StopTimer('timer2');">Stop All</button>
    <button onclick="ResetTimer('timer1');">Reset Timer1</button>
    <button onclick="ResetTimer('timer2');">Reset Timer2</button>
    <button onclick="ResetAll();">Reset All</button>

    【讨论】:

      【解决方案2】:

      重置动画:

      // Remove style
      $("#timer-bar").removeAttr('style');
      // Set initial width
      $("#timer-bar").show().width("100%");
      

      或:

      $('#timer-bar').stop(true).css('width', '100%');
      

      【讨论】:

      • 第一个确实可以像我想要的那样重置条形宽度!我确实注意到以这种方式重置它会留下 jqueryui 创建的效果占位符,所以我也需要手动删除该元素。我暂时不会将其标记为已解决,因为我想看看是否有适当的 API 方法来处理我的案例。感谢您的帮助!
      【解决方案3】:

      您可以在开始时.clone() timer1 并在timer2 效果结束时使用.replaceWith() 将其重置为初始值:

      var initialValue = null;
      function StartTimer1() {
          if (initialValue == null) {
              initialValue = $("#timer1").clone();
          } else {
              $("#timer1").replaceWith(initialValue);
          }
          $("#timer1").show().width("100%");
      
          $("#timer1").hide({
              effect: "blind",
              easing: "linear",
              duration: 5000,
              direction: "left",
              complete: function () {
              }
          });
      }
      
      function StopTimer1(){
          $("#timer1").stop(true, false);
      
          $("#timer2").hide({
              effect: "blind",
              easing: "linear",
              duration: 2000,
              direction: "left",
              complete: function () {
                  StartTimer1();
              }
          });
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
      
      <div id="timer1" style="height:30px; width:100%; background-color:red"></div>
      <div id="timer2" style="height:30px; width:100%; background-color:blue"></div>
      Click First button, then click second, then click first again
      <button onclick="StartTimer1();">Start Timer1</button><button onclick="StopTimer1();">Stop Timer1 and Start Timer2</button>

      【讨论】:

        【解决方案4】:

        使用 .stop(true, true) 去掉占位符 (.stop( [clearQueue ] [, jumpToEnd ] ))。 jumpToEnd 会隐藏,所以再显示一遍,timer2结束后回调:

         function StartTimer1() {
          $("#timer1").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function() {}
          });
        }
        
        function StopTimer1() {
          $("#timer1").stop(true, true).show();
        
          $("#timer2").hide({
            effect: "blind",
            easing: "linear",
            duration: 2000,
            direction: "left",
            complete: function() {
              StartTimer1()
            }
          });
        }
        

        点击按钮后立即重置红色条的示例:

        function StartTimer1() {
          $("#timer1").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function() {}
          });
        }
        
        function StopTimer1() {
          $("#timer1").stop(true, true).show();
        
          $("#timer2").hide({
            effect: "blind",
            easing: "linear",
            duration: 2000,
            direction: "left",
            complete: function() {
              StartTimer1()
            }
          });
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
        <div id="timer1" style="height:30px; width:100%; background-color:red">
        
        </div>
        
        
        <div id="timer2" style="height:30px; width:100%; background-color:blue">
        
        </div>
        
        Click First button, then click second, then click first again
        <button onclick="StartTimer1();">
        Start Timer1
        </button>
        
        
        <button onclick="StopTimer1();">
        Stop Timer1 and Start Timer2
        </button>

        如果你想在蓝色动画完成后重置红色条:

        使用.stop(true, false); 并在蓝条完成后重置样式 (.attr("style")。

        function StartTimer1() {
          $("#timer1").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function() {}
          });
        }
        
        function StopTimer1() {
          $("#timer1").stop(true, false);
        
          $("#timer2").hide({
            effect: "blind",
            easing: "linear",
            duration: 2000,
            direction: "left",
            complete: function() {
              $("#timer1").attr("style", "height:30px; width:100%; background-color:red");
              StartTimer1();
            }
          });
        }
        

        function StartTimer1() {
          $("#timer1").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function() {}
          });
        }
        
        function StopTimer1() {
          $("#timer1").stop(true, false);
        
          $("#timer2").hide({
            effect: "blind",
            easing: "linear",
            duration: 2000,
            direction: "left",
            complete: function() {
              $("#timer1").attr("style", "height:30px; width:100%; background-color:red");
              StartTimer1();
            }
          });
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
        <div id="timer1" style="height:30px; width:100%; background-color:red">
        
        </div>
        
        
        <div id="timer2" style="height:30px; width:100%; background-color:blue">
        
        </div>
        
        Click First button, then click second, then click first again
        <button onclick="StartTimer1();">
        Start Timer1
        </button>
        
        
        <button onclick="StopTimer1();">
        Stop Timer1 and Start Timer2
        </button>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-14
          • 2012-02-15
          • 2012-06-19
          • 1970-01-01
          • 2013-03-01
          • 1970-01-01
          相关资源
          最近更新 更多