I’m working on a photo slider made by HTML+CSS+JS. Currently it has navigation arrows, dots, and autoplay function. The animation changes its direction according to the interaction with the corresponding arrows/dots, and it resets the timer on each click. I’m trying to improve it step by step, and currently into adding a progress bar that’ll fill automatically based on sliderSpeed
.
Could you please help?
var timeout;
function setDirection(d) {
document.querySelector('.slider').style.setProperty('--direction', d);
}
setDirection(1);
var slider = document.getElementsByClassName("slider")[0];
var sliderDots = Array.prototype.slice.call(document.getElementsByClassName("dots")[0].children);
var sliderContents = Array.prototype.slice.call(document.getElementsByClassName("elements")[0].children);
var sliderArrowLeft = document.getElementsByClassName("arrow-left")[0];
var sliderArrowRight = document.getElementsByClassName("arrow-right")[0];
var sliderSpeed = 4000,
currentSlide = 0,
currentActive = 0,
sliderTimer = 0;
function playSlide(slide, d) {
if (!(d === undefined)) {
direction = d;
setDirection(d);
// Force it forwards after it's done:
clearTimeout(timeout);
timeout = setTimeout(function() {
setDirection(1);
}, 1000)
}
for (var k = 0; k < sliderDots.length; k++) {
sliderContents[k].classList.remove("active");
sliderContents[k].classList.remove("inactive");
sliderDots[k].classList.remove("active");
}
if (slide < 0) {
slide = currentSlide = sliderContents.length - 1;
}
if (slide > sliderContents.length - 1) {
slide = currentSlide = 0;
}
if (currentActive != currentSlide) {
sliderContents[currentActive].classList.add("inactive");
}
sliderContents[slide].classList.add("active");
sliderDots[slide].classList.add("active");
currentActive = currentSlide;
clearTimeout(sliderTimer);
sliderTimer = setTimeout(function() {
playSlide(currentSlide += 1);
}, sliderSpeed)
}
sliderArrowLeft.addEventListener("click", function() {
playSlide(currentSlide -= 1, -1);
})
sliderArrowRight.addEventListener("click", function() {
playSlide(currentSlide += 1, 1);
})
for (var l = 0; l < sliderDots.length; l++) {
sliderDots[l].addEventListener("click", function() {
let d = sliderDots.indexOf(this) - currentSlide
playSlide(currentSlide = sliderDots.indexOf(this), Math.sign(d));
})
}
playSlide(currentSlide);
.slider {
overflow: hidden;
position: relative;
}
.contents {
width: 100%;
height: 200px;
position: relative;
overflow: hidden;
}
.arrow-left,
.arrow-right {
width: 50px;
height: 50px;
bottom: 0;
cursor: pointer;
display: block;
text-align: center;
line-height: 50px;
background: rgb(200, 200, 200);
position: absolute;
z-index: 2;
}
.arrow-left {
left: 0;
}
.arrow-right {
right: 0;
}
.dots {
height: 14px;
bottom: 0;
left: 50%;
font-size: 0;
text-align: right;
position: absolute;
z-index: 2;
transform: translateX(-50%);
}
.dot {
width: 12px;
height: 12px;
margin-left: 5px;
margin-right: 5px;
display: inline-block;
cursor: pointer;
border-style: solid;
border-width: 1px;
border-color: rgb(100, 100, 100);
}
.dot.active {
background: rgb(200, 200, 200);
}
.elements {
width: 100%;
overflow: hidden;
transform: translate(0px);
}
.image {
width: 100%;
height: 100px;
top: 0;
position: absolute;
opacity: 0;
}
.image span {
width: 100%;
height: 100px;
text-align: center;
line-height: 100px;
display: block;
background: rgb(200, 200, 200);
}
.image.active {
position: relative;
z-index: 1;
opacity: 1;
}
.image.inactive {
z-index: -3;
opacity: 1;
}
.image.active span {
animation: show .5s ease-in-out forwards;
}
.image.inactive span {
animation: hide .5s ease-in-out forwards;
}
@keyframes show {
0% {
transform: translateX(calc(var(--direction)*100%));
}
100% {
transform: translateX(0);
}
}
@keyframes hide {
0% {
opacity: 1;
transform: translateX(0);
}
100% {
opacity: 0;
transform: translateX(calc(-1*var(--direction)*100%));
}
}
.bar-holder {
width: 100%;
background: rgb(200, 200, 200);
}
.bar {
width: 10%;
height: 10px;
background: rgb(255,0,0);
}
<div class="slider">
<div class="contents">
<div class="arrow-left">prev</div>
<div class="arrow-right">next</div>
<div class="dots">
<li class="dot"></li>
<li class="dot"></li>
<li class="dot"></li>
</div>
<div class="elements">
<div class="image"><span>image 1</span></div>
<div class="image"><span>image 2</span></div>
<div class="image"><span>image 3</span></div>
</div>
</div>
<div class="bar-holder">
<div class="bar"></div>
</div>
</div>
2
Answers
add this function
and call it inside the playSlide function
I edited your snipped such that it uses a CSS animation. The duration of the animation is set using javascript in the first line of your
playSlide()
function.This uses the efficiency of the browsers css rendering engine.
I marked the lines that I changed with comments, e.g.
//====Line added====