防止自定义jQuery图像轮播中的事件重叠 [英] Prevent event overlap in custom jQuery image carousel

查看:38
本文介绍了防止自定义jQuery图像轮播中的事件重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我在下面发布的解决方案还不够好,因为它使除了有效的 对点击不响应 以外的所有项目符号,而不是 排队 进行改进.

UPDATE: the solution I have posted below is not good enough, because it makes all the bullets except the active one non-responsive to clicks, instead of queueing them, so there is room for improvement.

我正在使用jQuery和CSS制作自定义图像轮播.我的目标是使它真正轻巧,但具有(仅)足够的功能:项目符号",自动前进,响应能力.

I am working on a custom image carousel, using jQuery and CSS. My aim is to make it really lightweight but with (just) enough features: "bullets", auto-advance, responsiveness.

工作正常,但我发现了一个无法修复的错误:当我快速连续单击2个项目符号时-这意味着在第二个项目符号触发的转换完成之前单击第二个项目符号-过渡以一种我无法描述的怪异方式重叠,但可以在下面看到:

It works fine, but I have discovered a bug I was unable to fix: when I click 2 bullets in rapid succession - which means clicking the second before the transition triggered by the first is finished - the transitions overlap in a weird manner I can not describe but is visible below:

var $elm = $('.slider'),
  $slidesContainer = $elm.find('.slider-container'),
  slides = $slidesContainer.children('a'),
  slidesCount = slides.length,
  slideHeight = $(slides[0]).find('img').outerHeight(false),
  animationspeed = 1500,
  animationInterval = 7000;

// Set (initial) z-index for each slide
var setZindex = function() {
  for (var i = 0; i < slidesCount; i++) {
    $(slides[i]).css('z-index', slidesCount - i);
  }
};
setZindex();

var displayImageBeforeClick = null;

var setActiveSlide = function() {
  $(slides).removeClass('active');
  $(slides[activeIdx]).addClass('active');
};

var advanceFunc = function() {
  if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
    $('.slider-nav li.activeSlide').next().find('a').trigger('click');
  } else {
    $('.slider-nav li:first').find('a').trigger('click');
  }
}

var autoAdvance = setInterval(advanceFunc, animationInterval);

//Set slide height
$(slides).css('height', slideHeight);

// Append bullets
if (slidesCount > 1) {
  /* Prepend the slider navigation to the slider
     if there are at least 2 slides */
  $elm.prepend('<ul class="slider-nav"></ul>');
  
  // make a bullet for each slide
  for (var i = 0; i < slidesCount; i++) {
    var bullets = '<li><a href="#">' + i + '</a></li>';
    if (i == 0) {
      // active bullet
      var bullets = '<li class="activeSlide"><a href="#">' + i + '</a></li>';
      // active slide
      $(slides[0]).addClass('active');
    }
    $('.slider-nav').append(bullets);
  }
};

var slideUpDown = function() {
  // set top property for all the slides
  $(slides).not(displayImageBeforeClick).css('top', slideHeight);
  // then animate to the next slide
  $(slides[activeIdx]).animate({
    'top': 0
  }, animationspeed);

  $(displayImageBeforeClick).animate({
    'top': "-100%"
  }, animationspeed);
};

$('.slider-nav a').on('click', function(event) {
  displayImageBeforeClick = $(".slider-container .active");
  activeIdx = $(this).text();
  if ($(slides[activeIdx]).hasClass("active")) {
    return false;
  }
  $('.slider-nav a').closest('li').removeClass('activeSlide');
  $(this).closest('li').addClass('activeSlide');

  // Reset autoadvance if user clicks bullet
  if (event.originalEvent !== undefined) {
    clearInterval(autoAdvance);
    autoAdvance = setInterval(advanceFunc, animationInterval);
  }

  setActiveSlide();
  slideUpDown();
});

body * {
  box-sizing: border-box;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
}

.slider {
  width: 100%;
  height: 300px;
  position: relative;
  overflow: hidden;
}

.slider .slider-nav {
  text-align: center;
  position: absolute;
  padding: 0;
  margin: 0;
  left: 10px;
  right: 10px;
  bottom: 2px;
  z-index: 30;
}

.slider .slider-nav li {
  display: inline-block;
  width: 20px;
  height: 3px;
  margin: 0 1px;
  text-indent: -9999px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, .5);
}

.slider .slider-nav a {
  display: block;
  height: 3px;
  line-height: 3px;
}

.slider .slider-nav li.activeSlide {
  background: #fff;
}

.slider .slider-nav li.activeSlide a {
  display: none;
}

.slider .slider-container {
  width: 100%;
  text-align: center;
}

.slider .slider-container a {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.slider .slider-container img {
  transform: translateX(-50%);
  margin-left: 50%;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div class="container">
  <div class="slider slider-homepage">
    <div class="slider-container">
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=east" alt="">
      </a>
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=south" alt="">
      </a>
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=west" alt="">
      </a>
    </div>
  </div>
</div>

如何避免这种因缺乏更好用词而被称为事件拥挤(重叠)的现象?

How could I prevent this phenomenon I would call, for lack of a better term, an event crowding (overlap)?

推荐答案

您可以使用来链接动画. jQuery延迟对象承诺.这是可让您轻松完成此课程的课程.

You can chain your animations using jQuery deferred object and Promise. Here is the class allowing you to do it easily.

var Queue = function() {
    var lastPromise = null;

    this.add = function(callable) {
        var methodDeferred = $.Deferred();
        var queueDeferred = this.setup();

        // execute next queue method
        queueDeferred.done(function() {

            // call actual method and wrap output in deferred
            callable().then(methodDeferred.resolve)
        });
        lastPromise = methodDeferred.promise();
    };

    this.setup = function() {
        var queueDeferred = $.Deferred();

        // when the previous method returns, resolve this one
        $.when(lastPromise).always(function() {
            queueDeferred.resolve();
        });

        return queueDeferred.promise();
    }
};

摆弄着动画.

PS:我增加了按钮的大小以便更轻松地单击

PS: I increase the size of the buttons to click more easily

var $elm = $('.slider'),
  $slidesContainer = $elm.find('.slider-container'),
  slides = $slidesContainer.children('a'),
  slidesCount = slides.length,
  slideHeight = $(slides[0]).find('img').outerHeight(false),
  animationspeed = 1500,
  animationInterval = 7000;

// Set (initial) z-index for each slide
var setZindex = function() {
  for (var i = 0; i < slidesCount; i++) {
    $(slides[i]).css('z-index', slidesCount - i);
  }
};
setZindex();

var setActiveSlide = function() {
  $(slides).removeClass('active');
  $(slides[activeIdx]).addClass('active');
};

var advanceFunc = function() {
  if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
    $('.slider-nav li.activeSlide').next().find('a').trigger('click');
  } else {
    $('.slider-nav li:first').find('a').trigger('click');
  }
}

var autoAdvance = setInterval(advanceFunc, animationInterval);

//Set slide height
$(slides).css('height', slideHeight);

// Append bullets
if (slidesCount > 1) {
  /* Prepend the slider navigation to the slider
     if there are at least 2 slides */
  $elm.prepend('<ul class="slider-nav"></ul>');
  
  // make a bullet for each slide
  for (var i = 0; i < slidesCount; i++) {
    var bullets = '<li><a href="#">' + i + '</a></li>';
    if (i == 0) {
      // active bullet
      var bullets = '<li class="activeSlide"><a href="#">' + i + '</a></li>';
      // active slide
      $(slides[0]).addClass('active');
    }
    $('.slider-nav').append(bullets);
  }
};

var Queue = function() {
    var lastPromise = null;

    this.add = function(callable) {
        var methodDeferred = $.Deferred();
        var queueDeferred = this.setup();
        // execute next queue method
        queueDeferred.done(function() {

            // call actual method and wrap output in deferred
            callable().then(methodDeferred.resolve)
        });
        lastPromise = methodDeferred.promise();
    };

    this.setup = function() {
        var queueDeferred = $.Deferred();
        // when the previous method returns, resolve this one
        $.when(lastPromise).always(function() {
            queueDeferred.resolve();
        });
        return queueDeferred.promise();
    }
};

var queue = new Queue();
var slideUpDown = function(previousIdx, activeIdx) {
  queue.add(function() {
    return new Promise(function(resolve, reject) {
      // set top property for all the slides
      $(slides).not(slides[previousIdx]).css('top', slideHeight);
      // then animate to the next slide
      $(slides[activeIdx]).animate({
        'top': 0
      }, animationspeed);

      $(slides[previousIdx]).animate({
        'top': "-100%"
      }, animationspeed, 'swing', resolve);
    })
  })
};

var previousIdx = '0' // First slide
$('.slider-nav a').on('click', function(event) {
  activeIdx = $(this).text();
  
  // Disable clicling on an active item
  if ($(slides[activeIdx]).hasClass("active")) {
    return false;
  }
  $('.slider-nav a').closest('li').removeClass('activeSlide');
  $(this).closest('li').addClass('activeSlide');

  // Reset autoadvance if user clicks bullet
  if (event.originalEvent !== undefined) {
    clearInterval(autoAdvance);
    autoAdvance = setInterval(advanceFunc, animationInterval);
  }

  setActiveSlide();
  slideUpDown(previousIdx, activeIdx);
	previousIdx = activeIdx
});

body * {
  box-sizing: border-box;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
}

.slider {
  width: 100%;
  height: 300px;
  position: relative;
  overflow: hidden;
}

.slider .slider-nav {
  text-align: center;
  position: absolute;
  padding: 0;
  margin: 0;
  left: 10px;
  right: 10px;
  bottom: 2px;
  z-index: 30;
}

.slider .slider-nav li {
  display: inline-block;
  width: 20px;
  height: 6px;
  margin: 0 1px;
  text-indent: -9999px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, .5);
}

.slider .slider-nav a {
  display: block;
  height: 6px;
  line-height: 3px;
}

.slider .slider-nav li.activeSlide {
  background: #fff;
}

.slider .slider-nav li.activeSlide a {
  display: none;
}

.slider .slider-container {
  width: 100%;
  text-align: center;
}

.slider .slider-container a {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.slider .slider-container img {
  transform: translateX(-50%);
  margin-left: 50%;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div class="container">
  <div class="slider slider-homepage">
    <div class="slider-container">
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=east" alt="">
      </a>
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=south" alt="">
      </a>
      <a href="#">
        <img src="https://picsum.photos/1200/300/?gravity=west" alt="">
      </a>
    </div>
  </div>
</div>

这篇关于防止自定义jQuery图像轮播中的事件重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆