xander17
xander17

Reputation: 141

Infinite Carousel Javascript

I am trying to build an infinite carousel and everything works fine when I press the next button but when I press prev the last child is prepended after transition end and not look good.

I tried to also prepend it on transition start but the same thing is happening.How can I do it smoothly? You have the code below.Thank you!

const wrapper = document.querySelector('.wrapper');
const container = document.querySelector('.container');
const children = wrapper.querySelectorAll('.child');
const leftArr = document.querySelector('.left-arrow');
const rightArr = document.querySelector('.right-arrow');

let counter = 0;
let infiniteCounter = 0;


  container.addEventListener('click', function(e) {
    wrapper.style.transition = '.5s ease all';
    if(e.target.classList.contains('left-arrow')) { 
      infiniteCounter = -1;
      counter += 20;
      wrapper.style.transform = `translateX(${counter}%)`;
    }
    
    if(e.target.classList.contains('right-arrow')) {
      infiniteCounter = 1;
      counter -= 20;
      wrapper.style.transform = `translateX(${counter}%)`;
    }
    
  });

let infiniteCarousel = function() {
  wrapper.style.transition = 'none';
  counter = 0;
  
  if(infiniteCounter === 1) {
     wrapper.appendChild(wrapper.firstElementChild);
     wrapper.style.transform = `translateX(0%)`;
  }
  
  if(infiniteCounter === -1) {
     wrapper.style.transform = `translateX(0%)`;
     wrapper.prepend(wrapper.lastElementChild);
  }
}

wrapper.addEventListener('transitionend', infiniteCarousel);
body {
  display: flex;
  justify-content:center;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  position: relative;
  background: black;
  width: 80vw;
  overflow: hidden;
}

.wrapper {
  display: flex;
  justify-content: flex-start;
  width: 100%;
  transition: .5s ease all;
}

.left-arrow, .right-arrow {
  display: flex;
  cursor: pointer;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  color: white;
  width: 50px;
  height: 50px;
  background: #ED4956;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}

.left-arrow {
  left: 2%;
  top: 50%;
}

.right-arrow {
  left: 98%;
  top: 50%;
}

.child {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
  height: 250px;
  width: 20%;
  font-weight: bold;
  font-size: 4rem;
}

.child1 {
  background: green;
}

.child2 {
  background: blue;
}

.child3 {
  background: yellow;
}

.child4 {
  background: navy;
}

.child5 {
  background: red;
}

.child6 {
  background: pink;
}

.child7 {
  background: grey;
}

.child8 {
  background: brown;
}

.child9 {
  background: #ff80ed;
}
<div class="container">
  <div class="wrapper">
    <div class="child child1">1</div>
    <div class="child child2">2</div>
    <div class="child child3">3</div>
    <div class="child child4">4</div>
    <div class="child child5">5</div>
    <div class="child child6">6</div>
    <div class="child child7">7</div>
    <div class="child child8">8</div>
    <div class="child child9">9</div>
  </div>
    <div class="left-arrow"> &larr; </div>
    <div class="right-arrow"> &rarr; </div>
</div>

Upvotes: 1

Views: 1296

Answers (2)

Tom
Tom

Reputation: 263

The issue you're having is that the previous element doesn't exist and it takes the browser time to put that element there. One way to fix it is to move the whole carousel to the left. This way the first element will be hidden. I added "left: -20%; position: relative" to the wrapper and seems much better

const wrapper = document.querySelector('.wrapper');
const container = document.querySelector('.container');
const children = wrapper.querySelectorAll('.child');
const leftArr = document.querySelector('.left-arrow');
const rightArr = document.querySelector('.right-arrow');

let counter = 0;
let infiniteCounter = 0;


  container.addEventListener('click', function(e) {
    wrapper.style.transition = '.5s ease all';
    if(e.target.classList.contains('left-arrow')) { 
      infiniteCounter = -1;
      counter += 20;
      wrapper.style.transform = `translateX(${counter}%)`;
    }
    
    if(e.target.classList.contains('right-arrow')) {
      infiniteCounter = 1;
      counter -= 20;
      wrapper.style.transform = `translateX(${counter}%)`;
    }
    
  });

let infiniteCarousel = function() {
  wrapper.style.transition = 'none';
  counter = 0;
  
  if(infiniteCounter === 1) {
     wrapper.appendChild(wrapper.firstElementChild);
     wrapper.style.transform = `translateX(0%)`;
  }
  
  if(infiniteCounter === -1) {
     wrapper.style.transform = `translateX(0%)`;
     wrapper.prepend(wrapper.lastElementChild);
  }
}

wrapper.addEventListener('transitionend', infiniteCarousel);
body {
  display: flex;
  justify-content:center;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  position: relative;
  background: black;
  width: 80vw;
  overflow: hidden;
}

.wrapper {
  display: flex;
  justify-content: flex-start;
  width: 100%;
  transition: .5s ease all;
  left: -20%;
  position: relative;
}

.left-arrow, .right-arrow {
  display: flex;
  cursor: pointer;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  color: white;
  width: 50px;
  height: 50px;
  background: #ED4956;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}

.left-arrow {
  left: 2%;
  top: 50%;
}

.right-arrow {
  left: 98%;
  top: 50%;
}

.child {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
  height: 250px;
  width: 20%;
  font-weight: bold;
  font-size: 4rem;
}

.child1 {
  background: green;
}

.child2 {
  background: blue;
}

.child3 {
  background: yellow;
}

.child4 {
  background: navy;
}

.child5 {
  background: red;
}

.child6 {
  background: pink;
}

.child7 {
  background: grey;
}

.child8 {
  background: brown;
}

.child9 {
  background: #ff80ed;
}
<div class="container">
  <div class="wrapper">
    <div class="child child1">1</div>
    <div class="child child2">2</div>
    <div class="child child3">3</div>
    <div class="child child4">4</div>
    <div class="child child5">5</div>
    <div class="child child6">6</div>
    <div class="child child7">7</div>
    <div class="child child8">8</div>
    <div class="child child9">9</div>
  </div>
    <div class="left-arrow"> &larr; </div>
    <div class="right-arrow"> &rarr; </div>
</div>

Upvotes: 3

MHassan
MHassan

Reputation: 435

const wrapper = document.querySelector('.wrapper');
const container = document.querySelector('.container');
const children = wrapper.querySelectorAll('.child');
const leftArr = document.querySelector('.left-arrow');
const rightArr = document.querySelector('.right-arrow');

let counter = 0;
let infiniteCounter = 0;


  container.addEventListener('click', function(e) {
    wrapper.style.transition = '.5s ease all';
    if(e.target.classList.contains('left-arrow')) { 
      infiniteCounter = -1;
      counter += 20;
      wrapper.style.transform = `translateX(${counter}%)`;
      wrapper.style.transform = `translateX(0%)`;
      wrapper.prepend(wrapper.lastElementChild);
    }
    
    if(e.target.classList.contains('right-arrow')) {
      infiniteCounter = 1;
      counter -= 20;
      wrapper.style.transform = `translateX(${counter}%)`;
      wrapper.appendChild(wrapper.firstElementChild);
      wrapper.style.transform = `translateX(0%)`;
    }
    
  });

let infiniteCarousel = function() {
  wrapper.style.transition = 'none';
  counter = 0;
  
  
  
}

wrapper.addEventListener('transitionend', infiniteCarousel);
body {
  display: flex;
  justify-content:center;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  position: relative;
  background: black;
  width: 80vw;
  overflow: hidden;
}

.wrapper {
  display: flex;
  justify-content: flex-start;
  width: 100%;
  transition: .5s ease all;
}

.left-arrow, .right-arrow {
  display: flex;
  cursor: pointer;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  color: white;
  width: 50px;
  height: 50px;
  background: #ED4956;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
}

.left-arrow {
  left: 2%;
  top: 50%;
}

.right-arrow {
  left: 98%;
  top: 50%;
}

.child {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
  height: 250px;
  width: 20%;
  font-weight: bold;
  font-size: 4rem;
}

.child1 {
  background: green;
}

.child2 {
  background: blue;
}

.child3 {
  background: yellow;
}

.child4 {
  background: navy;
}

.child5 {
  background: red;
}

.child6 {
  background: pink;
}

.child7 {
  background: grey;
}

.child8 {
  background: brown;
}

.child9 {
  background: #ff80ed;
}
<div class="container">
  <div class="wrapper">
    <div class="child child1">1</div>
    <div class="child child2">2</div>
    <div class="child child3">3</div>
    <div class="child child4">4</div>
    <div class="child child5">5</div>
    <div class="child child6">6</div>
    <div class="child child7">7</div>
    <div class="child child8">8</div>
    <div class="child child9">9</div>
  </div>
    <div class="left-arrow"> &larr; </div>
    <div class="right-arrow"> &rarr; </div>
</div>

Upvotes: 0

Related Questions