Очередь событий клика в карусели Bootstrap 3 - PullRequest
0 голосов
/ 29 октября 2018

Я работаю над собственной каруселью Bootstrap 3, с вертикальными, однонаправленными, скользящими переходами. Вот оно в его текущем состоянии:

var carouselDuration = function() {
  $.fn.carousel.Constructor.TRANSITION_DURATION = 1000;
}
carouselDuration();
.carousel.vertical {
  position: relative;
}

.carousel.vertical .carousel-inner {
  height: 100%;
  width: auto;
}

.carousel.vertical .carousel-inner>.item {
  width: auto;
  transition: 1s ease-in-out;
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.next,
.carousel.vertical .carousel-inner>.prev,
.carousel.vertical .carousel-inner>.right {
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.left,
.carousel.vertical .carousel-inner>.prev.right,
.carousel.vertical .carousel-inner>.next.left,
.carousel.vertical .carousel-inner>.active {
  transform: translate3d(0, 0, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.active.right,
.carousel.vertical .carousel-inner>.active.left {
  transform: translate3d(0, -100%, 0);
  top: 0;
}

.carousel.vertical .carousel-indicators {
  display: inline-block;
  width: auto;
  padding: 0;
  margin: 0;
  left: auto;
  right: 10px;
  bottom: 2px;
  z-index: 9;
  font-size: 0;
}

.carousel.vertical .carousel-indicators li {
  border: none;
  cursor: pointer;
  display: inline-block;
  width: 18px;
  height: 18px;
  text-indent: -9999px;
  background: url("https://grgs.ro/1/i/sprite.png") no-repeat -528px -502px;
}

.carousel.vertical .carousel-indicators li.active {
  background-position: -528px -524px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


<div class="container">
  <div id="myCarousel" class="carousel vertical slide" data-ride="carousel" data-interval="9000">
    <!-- Wrapper for slides -->
    <div class="carousel-inner">
      <div class="item active">
        <img src="https://picsum.photos/1200/300/?gravity=east" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=south" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=west" alt="">
      </div>
    </div>

    <!-- Indicators -->
    <ol class="carousel-indicators">
      <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
      <li data-target="#myCarousel" data-slide-to="1"></li>
      <li data-target="#myCarousel" data-slide-to="2"></li>
    </ol>
  </div>
</div>

Имеется ошибка: когда я нажимаю 2 пули в быстрой последовательности - что означает нажатие второй до завершения перехода, инициируемого первой - переходы перекрываются .

Это ошибка Bootstrap или ошибка вышеупомянутой карусели?

Какой простой и надежный способ предотвратить эту ошибку перекрытия?

Ответы [ 4 ]

0 голосов
/ 01 ноября 2018

Вот компромиссное решение: не ставить в очередь события щелчка, а отключать их, пока выполняется переход слайдов, а затем включать их между переходами:

var carouselDuration = function() {
  $.fn.carousel.Constructor.TRANSITION_DURATION = 1000;
}

carouselDuration();
// While a transition is in progress (slide event), do this
$('#myCarousel').on('slide.bs.carousel', function (e) {
    var $indicator = $(this).find('.carousel-indicators>li');
    $indicator.css('pointer-events', 'none');
});

// While a transition has finished (slid event), do this
$('#myCarousel').on('slid.bs.carousel', function (e) {
    var $indicator = $(this).find('.carousel-indicators>li');
    $indicator.css('pointer-events', 'auto');
});
.carousel.vertical {
  position: relative;
}

.carousel.vertical .carousel-inner {
  height: 100%;
  width: auto;
}

.carousel.vertical .carousel-inner>.item {
  width: auto;
  transition: 1s ease-in-out;
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.next,
.carousel.vertical .carousel-inner>.prev,
.carousel.vertical .carousel-inner>.right {
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.left,
.carousel.vertical .carousel-inner>.prev.right,
.carousel.vertical .carousel-inner>.next.left,
.carousel.vertical .carousel-inner>.active {
  transform: translate3d(0, 0, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.active.right,
.carousel.vertical .carousel-inner>.active.left {
  transform: translate3d(0, -100%, 0);
  top: 0;
}

.carousel.vertical .carousel-indicators {
  display: inline-block;
  width: auto;
  padding: 0;
  margin: 0;
  left: auto;
  right: 10px;
  bottom: 2px;
  z-index: 9;
  font-size: 0;
}

.carousel.vertical .carousel-indicators li {
  border: none;
  cursor: pointer;
  display: inline-block;
  width: 18px;
  height: 18px;
  text-indent: -9999px;
  background: url("https://grgs.ro/1/i/sprite.png") no-repeat -528px -502px;
}

.carousel.vertical .carousel-indicators li.active {
  background-position: -528px -524px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


<div class="container">
  <div id="myCarousel" class="carousel vertical slide" data-ride="carousel" data-interval="9000">
    <!-- Wrapper for slides -->
    <div class="carousel-inner">
      <div class="item active">
        <img src="https://picsum.photos/1200/300/?gravity=east" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=south" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=west" alt="">
      </div>
    </div>

    <!-- Indicators -->
    <ol class="carousel-indicators">
      <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
      <li data-target="#myCarousel" data-slide-to="1"></li>
      <li data-target="#myCarousel" data-slide-to="2"></li>
    </ol>
  </div>
</div>

Все еще ищем механизм организации очередей, так как он более естественный и элегантный.

0 голосов
/ 29 октября 2018

Я думаю, что вы должны прочитать о Карусель События https://www.w3schools.com/booTsTrap/bootstrap_ref_js_carousel.asp

Когда slide.bs.carousel (начать скольжение) вы можете отключить точки и включить их снова, когда (slid.bs.carousel) раздвижной имеет отделку

0 голосов
/ 29 октября 2018

Мужик, ты много работаешь с каруселями. Не беспокойтесь, вот теория: сначала вы фиксируете текущее время в миллисекундах, когда анимация запускается, теперь, когда вы знаете, что каждая ваша анимация занимает 1 секунду, фиксируйте следующее событие щелчка на элементе управления каруселью.

Теперь сравните задержки между двумя событиями, если это более 1 секунды (то есть 1000 мс), просто задержите событие щелчка на этом элементе управления каруселью с помощью setTimeout.

Проверьте фрагмент, сделайте как можно больше случайных нажатий на этих контроллерах:

var carouselDuration = function() {
  $.fn.carousel.Constructor.TRANSITION_DURATION = 1000;
}
carouselDuration();

var slideStarted, slideEnded; // declare variables for storing animation start and end time, don't assing values yet.
$('#myCarousel').on('slide.bs.carousel', function() {
  slideStarted = new Date().getTime(); // capture the animation start time;
  console.log('started'); // remove this later
}).on('slid.bs.carousel', function() {
  console.log('ended'); // remove this later
});

$('.carousel-indicators').find('li').on('click', function() {
  slideEnded = new Date().getTime(); // now capture the next click time;
  if (slideEnded - slideStarted < 1000) { // compare the difference, if it's more than your desired delay which is 1 second, delay the click event calculating the value and boooooom !!!!
    console.log('early click', slideEnded - slideStarted);
    setTimeout(function() {
      $(this).click();
    }, slideEnded - slideStarted);
  }
});
.carousel.vertical {
  position: relative;
}

.carousel.vertical .carousel-inner {
  height: 100%;
  width: auto;
}

.carousel.vertical .carousel-inner>.item {
  width: auto;
  transition: 1s ease-in-out;
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.next,
.carousel.vertical .carousel-inner>.prev,
.carousel.vertical .carousel-inner>.right {
  transform: translate3d(0, 100%, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.left,
.carousel.vertical .carousel-inner>.prev.right,
.carousel.vertical .carousel-inner>.next.left,
.carousel.vertical .carousel-inner>.active {
  transform: translate3d(0, 0, 0);
  top: 0;
}

.carousel.vertical .carousel-inner>.active.right,
.carousel.vertical .carousel-inner>.active.left {
  transform: translate3d(0, -100%, 0);
  top: 0;
}

.carousel.vertical .carousel-indicators {
  display: inline-block;
  width: auto;
  padding: 0;
  margin: 0;
  left: auto;
  right: 10px;
  bottom: 2px;
  z-index: 9;
  font-size: 0;
}

.carousel.vertical .carousel-indicators li {
  border: none;
  cursor: pointer;
  display: inline-block;
  width: 18px;
  height: 18px;
  text-indent: -9999px;
  background: url("https://grgs.ro/1/i/sprite.png") no-repeat -528px -502px;
}

.carousel.vertical .carousel-indicators li.active {
  background-position: -528px -524px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


<div class="container">
  <div id="myCarousel" class="carousel vertical slide" data-ride="carousel" data-interval="9000">
    <!-- Wrapper for slides -->
    <div class="carousel-inner">
      <div class="item active">
        <img src="https://picsum.photos/1200/300/?gravity=east" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=south" alt="">
      </div>

      <div class="item">
        <img src="https://picsum.photos/1200/300/?gravity=west" alt="">
      </div>
    </div>

    <!-- Indicators -->
    <ol class="carousel-indicators">
      <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
      <li data-target="#myCarousel" data-slide-to="1"></li>
      <li data-target="#myCarousel" data-slide-to="2"></li>
    </ol>
  </div>
</div>
0 голосов
/ 29 октября 2018

Решение Simpelist использует обратные вызовы по умолчанию, я думаю ..

$('#myCarousel').on('slide.bs.carousel', function () { // remove click option }).on('slid.bs.carousel', function() { // add click option })

Удаление опции щелчка можно выполнить с помощью простого свойства CSS.

$('ol.carousel-indicators>li').css('pointer-events', 'none');

и включите его с помощью:

$('ol.carousel-indicators>li').css('pointer-events', 'auto');

Самое элегантное решение - добавить класс и определить указатель-событие в вашей таблице стилей. И добавьте / удалите класс, когда сработают обратные вызовы.

.disableClick{pointer-events:none;}

В ответ на комментарий:

Чтобы поставить в очередь события клика, вы можете использовать:

$(this).queue()

Сохраняет сделанные клики в очереди. Более подробную информацию можно найти здесь

...