jquery 点击转盘移动幻灯片,但也重置间隔计时器

e4yzc0pl  于 2023-03-01  发布在  jQuery
关注(0)|答案(3)|浏览(127)

我已经拼凑了一些JS + jQuery,它可以通过幻灯片循环一个类,我还添加了允许手动移动的上一个/下一个链接。
我有两个问题,我无法解决,主要是由于我缺乏与JS的经验。

    • 问题1。**当您单击"下一页"或"上一页"时,间隔计时器将不间断地继续计时。这意味着如果您在间隔1.9秒后单击"下一页",您移动到的幻灯片将只显示0.1秒。理想情况下,我希望计时器在单击时重置,但无法使其工作。
    • 问题2.**可怕的冗长代码。我通常坚持简洁的代码,但这是非常臃肿的,我曾尝试将变量移出函数,以便它们可以共享,但这似乎打破了旋转木马与活动类跳过第一张或最后一张幻灯片。我认为必须有一个更简洁,更有效的方式将所有这些放在一起。
setInterval(
  function() {
    var item = $(".slide--active");
    var next = item.next(".slide").length == 0 ? $('.slide').first() : item.next(".slide");
    var number = $(".current--active");
    var succeeding = number.next(".current").length == 0 ? $('.current').first() : number.next(".current");
    item.removeClass("slide--active");
    next.toggleClass('slide--active');
    number.removeClass("current--active");
    succeeding.toggleClass('current--active');
  },
  2000)

$('.next').click(function() {
  var item = $(".slide--active");
  var next = item.next(".slide").length == 0 ? $('.slide').first() : item.next(".slide");
  var number = $(".current--active");
  var succeeding = number.next(".current").length == 0 ? $('.current').first() : number.next(".current");
  item.removeClass("slide--active");
  next.toggleClass('slide--active');
  number.removeClass("current--active");
  succeeding.toggleClass('current--active');
});

$('.prev').click(function() {
  var item = $(".slide--active");
  var prev = item.prev(".slide").length == 0 ? $('.slide').last() : item.prev(".slide");
  var number = $(".current--active");
  var preceding = number.prev(".current").length == 0 ? $('.current').last() : number.prev(".current");
  item.removeClass("slide--active");
  prev.toggleClass('slide--active');
  number.removeClass("current--active");
  preceding.toggleClass('current--active');
});
.pagination {
  display: flex;
}

.numbers {
  padding: 0 1em;
}

.slides {
  list-style: none;
  display: flex;
}

.slide {
  width: 4em;
  height: 4em;
  background: blue;
}

.slide--active {
  background: red;
}

.current {
  display: none;
}

.current.current--active {
  display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="pagination">
  <a href="#" class="prev">&larr;</a>
  <div class="numbers">
    <span class="current current--active">1</span>
    <span class="current">2</span>
    <span class="current">3</span> / <span class="total">3</span>
  </div>
  <a href="#" class="next">&rarr;</a>
</div>

<ul class="slides">
  <li class="slide slide--active"></li>
  <li class="slide"></li>
  <li class="slide"></li>
</ul>

同样在jsfidle上:https://jsfiddle.net/morgyface/3fbto2qu/52/

icomxhvb

icomxhvb1#

正如您在帖子中指出的,这里有很多代码,其中很多看起来是重复的,或者至少非常接近于在两个单击处理程序和传递给setInterval的函数之间重复。
所有基于现有类来确定下一张或上一张幻灯片的工作都是繁重的,并且会导致代码笨拙。我认为重要的概念飞跃是要认识到这里有一个重要的变量:活动索引。2当点击"上一页"或"下一页"按钮时,或者间隔触发时,活动索引会发生变化。3 UI只会更新以反映新的活动索引。
考虑到这一点,我将围绕 * state * 构建代码--更改了什么、活动索引和setIntervalsetTimeout的标识符,我们需要跟踪它们以清除它。
从这里开始,我将把渲染封装到一个函数中。这个函数将切换幻灯片上的活动类和分页状态。单击处理程序可以更新状态,然后调用渲染函数。setInterval可以做同样的事情。(我最终使用了setTimeout,但我认为这真的是一个品味问题。)
我得到的密码是:

const state = {
  index: $('.slide--active').index(),
  timer: null,
  timerDurationMilliseconds: 2000,
  numSlides: $('.slide').length
};

const decrementIndex = () => {
  let newIndex = state.index - 1;
  
  if (newIndex < 0) {
    newIndex = state.numSlides - 1;
  }
  
  state.index = newIndex;
};

const incrementIndex = () => {
  let newIndex = state.index + 1;
  
  if (newIndex >= state.numSlides) {
    newIndex = 0;
  }
  
  state.index = newIndex;
};

const render = () => {
  $('.current').each(function () {
    const $this = $(this);
    $this.toggleClass('current--active', $this.index() === state.index);
  });
  
  $('.slide').each(function () {
    const $this = $(this);
    $this.toggleClass('slide--active', $this.index() === state.index);
  });
  
  if (state.timer) {
    clearTimeout(state.timer);
  }
  
  state.timer = setTimeout(() => {
    incrementIndex();
    render();
  }, state.timerDurationMilliseconds);
};

$('.next').on('click', function () {
  incrementIndex();
  render();
});

$('.prev').on('click', function () {
  decrementIndex();
  render();
});

render();
.pagination {
  display: flex;
}

.numbers {
  padding: 0 1em;
}

.slides {
  list-style: none;
  display: flex;
}

.slide {
  width: 4em;
  height: 4em;
  background: blue;
}

.slide--active {
  background: red;
}

.current {
  display: none;
}

.current.current--active {
  display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="pagination">
  <a href="#" class="prev">&larr;</a>
  <div class="numbers">
    <span class="current current--active">1</span>
    <span class="current">2</span>
    <span class="current">3</span> / <span class="total">3</span>
  </div>
  <a href="#" class="next">&rarr;</a>
</div>

<ul class="slides">
  <li class="slide slide--active"></li>
  <li class="slide"></li>
  <li class="slide"></li>
</ul>

我还创建了一个fiddle以供参考。

cetgtptt

cetgtptt2#

对于for neat concise code

const
  slidesList    = document.querySelectorAll('.slides > li')
, btNext        = document.querySelector('#next')
, btPrev        = document.querySelector('#prev')
, currentNumber = document.querySelector('.numbers > span:first-of-type')
, slide = 
  { index   : 0
  , max     : slidesList.length
  , refIntv : 0
  , delay   : 2000
  };
// init...
movSlide();
slide.refIntv = setInterval( movSlide, slide.delay, 1);
document.querySelector('.numbers > span:last-of-type').textContent = slide.max;

btNext.onclick =()=>{ btMove( +1) }
btPrev.onclick =()=>{ btMove( -1) }

function btMove(val)
  {
  clearInterval(slide.refIntv);
  movSlide( val );
  slide.refIntv = setInterval( movSlide, slide.delay, 1);
  }
function movSlide( move = 0 )
  {
  slide.index += slide.max + move;
  slide.index %= slide.max;
  currentNumber.textContent = slide.index +1; 

  slidesList.forEach( (elm, i) => elm.classList.toggle('slide--active', slide.index===i) );
  }
.pagination {
  display    : flex;
  }
.numbers {
  padding : 0.3em 1em 0 1em;
  }
.slides {
  list-style : none;
  display    : flex;
  column-gap : 5px;
  }
.slides > li {
  width      : 4em;
  height     : 4em;
  background : blue;
  }
.slides > li.slide--active {
  background : red;
  }
<div class="pagination">
  <button id="prev">&larr;</button>
  <div class="numbers">
    <span></span> / <span></span>
  </div>
  <button id="next">&rarr;</button>
</div>

<ul class="slides">
  <li></li> <li></li> <li></li> <li></li> <li></li> <li></li>
</ul>

但是如果你想在你的界面中保持一致性,它应该像这样工作:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个

wfsdck30

wfsdck303#

let variable = setInterval(()=>{})
clearInterval(variable)

这是重置间隔的方法......

相关问题