I am trying to build my own carousel with pure JavaScript.
I'm struggling with picking up the most efficient way to add an infinite carousel
option.
For some reasons, every element (photo, generic object) must have an id
The algorithm I see goes like that:
- You check if the carousel is overflown (the are enough objects to fit the whole container)
- If not: append to the back a copy of the first element, then a copy of the second element and so on. (But there will be an issue with the ids, because this object will have the same id)
- If the user is scrolling to the last object (to right) then append
the first DOM object to the array back
- If the user is scrolling to
the first object (to left) then add the last DOM child to array
front.
Is this going to work? Is there any other efficient way of doing an infinite carousel?
I have also heard that it's better to use translate property rather than changing the left, right properties, so it there would be more work for the GPU than for CPU.
I am trying to build my own carousel with pure JavaScript.
I'm struggling with picking up the most efficient way to add an infinite carousel
option.
For some reasons, every element (photo, generic object) must have an id
The algorithm I see goes like that:
- You check if the carousel is overflown (the are enough objects to fit the whole container)
- If not: append to the back a copy of the first element, then a copy of the second element and so on. (But there will be an issue with the ids, because this object will have the same id)
- If the user is scrolling to the last object (to right) then append
the first DOM object to the array back
- If the user is scrolling to
the first object (to left) then add the last DOM child to array
front.
Is this going to work? Is there any other efficient way of doing an infinite carousel?
I have also heard that it's better to use translate property rather than changing the left, right properties, so it there would be more work for the GPU than for CPU.
Share Improve this question edited Sep 24, 2016 at 7:22 Denis Rozimovschii asked Sep 24, 2016 at 7:02 Denis RozimovschiiDenis Rozimovschii 4481 gold badge6 silver badges20 bronze badges 7- 1 I guess you should rather try circular approach. This will ensure your not flooding DOM – Rajesh Commented Sep 24, 2016 at 7:19
- Could you please elaborate? – Denis Rozimovschii Commented Sep 24, 2016 at 7:20
- 1 Consider you have just 3 images. On click of next button fetch an element after it. If its the last element, pick first and animate it in a way its next. Do same for previous element. – Rajesh Commented Sep 24, 2016 at 7:23
- Great idea! So I don't actually change the DOM, but only move the things around. That's great. Still, the question remains for the copied elements. What if the carousel isn't overflown? Should I just move from id's to classes? – Denis Rozimovschii Commented Sep 24, 2016 at 7:25
- Well that's not true. Try to use GSAP tweenmax if you want to have a performance-based animations. Check it out. – hdotluna Commented Sep 24, 2016 at 7:26
2 Answers
Reset to default 12I created a simple slider with css transformations as the animation technique and plain Javascript.
var img = document.getElementsByClassName("img")[0];
img.style.transform = 'translate('+value+'px)';
You can test it in this codepen snippet. http://codepen.io/TobiObeck/pen/QKpaBr
A press on a button translates all images in the respective direction along the x-axis. An image on the edge, is set transparent outerImg.style.opacity = '0';
and translated to the other side. You can add or remove image elements in HTML and it still works.
In this second codepen snippet you can see how it works. The opacity
is set to 0.5
so it is observable which image switches the side. Because overflow: hidden
is removed, you can see how the images on the edge enqueue on the other side.
http://codepen.io/TobiObeck/pen/WGpdLE
Moreover it is notworthy that it is checked wether the animation is complete, otherwise the simultaneously added translations would look odd. Therefore a click won't trigger another animation until unless the animation is completed.
img.addEventListener("transitionend", transitionCompleted, true);
var transitionCompleted = function(){
translationComplete = true;
}
leftBtnCLicked(){
if(translationComplete === true){
//doAnimation
}
}
you can use this code to manipulate slides. This basically rotates the array back and front
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
width: 100%;
height: 100%;
}
.parentDiv {
height: 30%;
width: 100%;
display: flex;
}
</style>
<title>test</title>
</head>
<body>
<button class="fwd"> Fwd! </button>
<button class="bkwd"> Bkwd! </button>
<script type="text/javascript">
const arr = ['red', 'blue', 'coral', 'green', 'yellow'];
let narr = ['red', 'blue', 'coral'];
const parentDiv = document.createElement('div');
parentDiv.setAttribute('class', 'parentDiv');
document.body.insertAdjacentElement('afterbegin', parentDiv);
window.onload = ()=> {
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index]
});
};
document.querySelector('.fwd').addEventListener('click', ()=>{
narr.shift();
if(narr[narr.length-1] === arr[arr.length-1]){
narr.push(arr[0])
} else {
narr.push(arr[arr.indexOf(narr[narr.length-1])+1])
}
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index];
});
})
document.querySelector('.bkwd').addEventListener('click', ()=>{
narr.pop();
if(narr[0] === arr[0]){
narr.unshift(arr[arr.length-1])
} else {
narr.unshift(arr[arr.indexOf(narr[0])-1])
}
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index]
});
})
</script>
</body>
</html>