Home > Software design >  How to make a slider loop with JS?
How to make a slider loop with JS?

Time:10-03

maybe someone can tell me, how to make it so that when clicking next, the user sees an infinite loop of slider elements? At the moment, I was only able to make the elements move inside the slider. I'm assuming that I need to create new items inside the carousel on every click.

I would be grateful for advice on what to do next.

function sliderFunc() {
    let sliderBox = document.querySelector('.slider');
    let tapToRightBtn = document.querySelector('.btn');

    function sliderNext() {
        sliderBox.style.transform  = 'translateX(-100px)';
        sliderBox.style.transition = '0.3s';
    }
    tapToRightBtn.addEventListener('click', sliderNext);
}
sliderFunc();
.container {
  max-width: 300px;
  margin: auto;
  overflow: hidden;
}
.slider {
  background: #eee;
  display: flex;
  width: 500px;
  border: solid;
}
.slide {
  width: 200px;
  height: 100px;
  margin-right: 10px;
}
.slide1 {
  background: #f3ca63;
}
.slide2 {
  background: #d06c65;
}
.slide3 {
  background: #6579d0;
}
.slide4 {
  background: #65d073;
}
.slide5 {
  background: #ba65d0;
}
.btn {
  margin: 2rem;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<section >
  <div >
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </div>
  <button >Next</button>
</section>
</body>
</html>

CodePudding user response:

I made a simple script based on what you want. You may want to optimize it by removing the object(s) when they are not displayed.

What I have changed:

  1. Instead of transitioning using translateX(-100px), I make the container position relative then moving using left attribute (you're doing it wrong, you have to check for the value first then remove the px suffix)
  2. Make a timeout function to clone the object at index, then put it at the end of the slider object (have to increase the width and set the left style properly). The function sync exactly with the transition duration.

function sliderFunc() {
  let sliderBox = document.querySelector('.slider');
  let tapToRightBtn = document.querySelector('.btn');
  let index = 0;
  sliderBox.style.width = '500px';
  sliderBox.style.left = '0px';

  function sliderNext() {
    setTimeout(() => {
      index  ;
      let child = sliderBox.querySelector(`div:nth-child(${index})`);
      let cloneNode = child .cloneNode(true);
      sliderBox.style.width = `${(5   index) * 100}px`;
      sliderBox.appendChild(cloneNode);
    }, 300);
    // clone and move the element to bottom
    let currentLeftPosition = sliderBox.style.left ? parseFloat(sliderBox.style.left.replace('px', '')) : 0;
    let nextLeftPosition = currentLeftPosition - 100;
    sliderBox.style.left = `${nextLeftPosition}px`;

  }
  tapToRightBtn.addEventListener('click', sliderNext);
}
sliderFunc();
.container {
  max-width: 300px;
  margin: auto;
  overflow: hidden;
  position: relative;
}

.slider {
  background: #eee;
  display: flex;
  min-width: 500px;
  border: solid;
  position: relative;
  transition: left 0.3s;
}

.slide {
  width: 200px;
  height: 100px;
  margin-right: 10px;
}

.slide1 {
  background: #f3ca63;
}

.slide2 {
  background: #d06c65;
}

.slide3 {
  background: #6579d0;
}

.slide4 {
  background: #65d073;
}

.slide5 {
  background: #ba65d0;
}

.btn {
  margin: 2rem;
}
<section >
  <div >
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </div>
  <button >Next</button>
</section>

CodePudding user response:

ciao Stanley,

if I understood your question you can go with the following elegant solution

I will first explain the principles and advantages:

  • I won't add/remove any element, working only on your initial sliderBox
  • in order to create an infinite loop I'm stopping the shift move on this element that would be executed by sliderBox.style.transform = 'translateX(-100px)';
  • I modified sliderNext() so that the infinite slide effect will be achieved by stealing the color to the next slide, i.e. after clicking the Next button the 2nd slide will steal the color to the 3rd, the 3rd to the 4th and the 4th will be assigned each time a random color to give that endless feeling
  • I'm assuming that "infinite loop" meant that we don't want to see the border of sliderBox that would be shown with the 5th element, so we will never see it [you can add a "Go to the last element" button should you need that]
  • I did only minimal adjustments to your original draft, minimizing also any unneeded computational operations

Without further ado here is the final code:

function sliderFunc() {
  let sliderBox = document.querySelector('.slider');
  let tapToRightBtn = document.querySelector('.btn');
  let counter = 0;
  let firstSlide = document.querySelector('.slide2');
  let secondSlide = document.querySelector('.slide3');
  let thirdSlide = document.querySelector('.slide4');

  function sliderNext() {
    if (counter == 0) {
      sliderBox.style.transform  = 'translateX(-100px)';
      sliderBox.style.transition = '0.3s';
    } else {
      firstSlide.style.background = secondSlide.style.background;
      secondSlide.style.background = thirdSlide.style.background;
      thirdSlide.style.background = "#"   Math.floor(Math.random() * 16777215).toString(16);
    }
    counter  ;
  }
  tapToRightBtn.addEventListener('click', sliderNext);
}
sliderFunc();
.container {
  max-width: 300px;
  margin: auto;
  overflow: hidden;
}

.slider {
  background: #eee;
  display: flex;
  width: 500px;
  border: solid;
}

.slide {
  width: 200px;
  height: 100px;
  margin-right: 10px;
}

.slide1 {
  background: #f3ca63;
}

.slide2 {
  background: #d06c65;
}

.slide3 {
  background: #6579d0;
}

.slide4 {
  background: #65d073;
}

.slide5 {
  background: #ba65d0;
}

.btn {
  margin: 2rem;
}
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>

  <body>
    <section >
      <div >
        <div ></div>
        <div ></div>
        <div ></div>
        <div ></div>
        <div ></div>
      </div>
      <button >Next</button>
    </section>
  </body>

</html>

This should solve your problem, otherwise let me know

Have a good day,
Antonino

  • Related