Как сбросить анимацию эффекта JQueryUI? - PullRequest
2 голосов
/ 02 августа 2020

У меня есть две разные шкалы таймера, каждая из которых закрывается более 5 секунд. Но когда я пытаюсь остановить и сбросить первый таймер, он не сбрасывается, а продолжается только с того места, где он остановился.

Желаемое поведение: запускается таймер 1. Пользователь нажимает кнопку. Таймер 1 останавливается на полпути, запускается таймер 2. 100% и запускается

Вот как запускается таймер 1:

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
        }
    });

Затем по истечении таймера 2 я нажмите другую клавишу, которая снова вызывает StartTimer1 (). И хотя я сбрасываю ширину на 100% перед тем, как начать анимацию, она просто продолжается с того места, где была остановлена. Я читал об очередях и думал, что это был мой ответ, но я пробовал добавлять уникальные имена очередей к каждому из параметров таймера, но всякий раз, когда я это делаю, таймер по какой-то причине не запускается. То же самое, когда я просто установил для очереди значение true. Я пробовал разные варианты параметров clearQueue и jumpToEnd при вызове Stop (), но не могу добиться желаемого поведения.

Любая помощь будет принята с благодарностью. Спасибо.

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

Ответы [ 4 ]

2 голосов
/ 03 августа 2020

Анимация поверх методов скрытия и отображения?
Согласно моим исследованиям и этой публикации , у нас было бы больше контроля над анимацией, если бы мы использовали $(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>
1 голос
/ 03 августа 2020

Используйте .stop(true, true), чтобы получить оболочку заполнителя (.stop( [clearQueue ] [, jumpToEnd ] )). jumpToEnd скроет его, поэтому просто покажите его снова и перезвоните после окончания таймера 2:

 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); и сбросьте style (.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>
1 голос
/ 03 августа 2020

Вы можете .clone () timer1 в начале и сбросить его до исходного значения с помощью .replaceWith () , когда эффект timer2 закончится:

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>
1 голос
/ 03 августа 2020

Для сброса анимации:

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

или:

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