Unable to add automatic "next slide" to my image slideshow - javascript

I am unable to add a automatic function that shows the next image in my slideshow. I have tried different approaches i found on this forum using setinterval() alas to no success.
Here is a snippet of the JS code.
const pizzaSlide = document.querySelector(".pizza-slide");
const pizzaImages = document.querySelectorAll(".pizza-slide img"); //Selector for all images
//Buttons
const prevBtn = document.querySelector("#prevBtn");
const nextBtn = document.querySelector("#nextBtn");
//Counter - To figure out what image we are on we need a counter.
let counter = 1; //Starting from the first image
const size = pizzaImages[0].clientWidth; //Width of the image, so we know how much we need to slide.
pizzaSlide.style.transform = "translateX(" + (-size * counter ) + "px)"; //Moves one picture forward
//Timer
let timer = setInterval(() => pluscounter(1), 1000); - does not work.
//Button Listeners
nextBtn.addEventListener("click",()=>{ //Listens on click - adds transition
if(counter >= pizzaImages.length -1) return; //This is to prevent slideshow bugging out if nextBtn is clicked too fast.
pizzaSlide.style.transition = "transform 0.4s ease-in-out"; // The speed of the transitions.
counter++; //Adds one to counter
pizzaSlide.style.transform = "translateX(" + (-size * counter ) + "px)";
setInterval(nextBtn, 500);
});
prevBtn.addEventListener("click",()=>{ //Listens on click - adds transition
if (counter <= 0) return; //This is to prevent slideshow bugging out if prevBtn is clicked too fast.
pizzaSlide.style.transition = "transform 0.4s ease-in-out"; // The speed of the transitions.
counter--; //Retracts one from counter
pizzaSlide.style.transform = "translateX(" + (-size * counter ) + "px)";
});
pizzaSlide.addEventListener("transitionend", ()=>{ //Returns back to original image after the transform finishes - resets the transition if the picture is a "clone".
if(pizzaImages[counter].id === "lastClone"){
pizzaSlide.style.transition = "none"; //Translates it back to original picture
counter = pizzaImages.length -2;
pizzaSlide.style.transform = "translateX(" + (-size * counter ) + "px)";
}
if(pizzaImages[counter].id === "firstClone"){
pizzaSlide.style.transition = "none";
counter = pizzaImages.length - counter; //Translates it back to original picture
pizzaSlide.style.transform = "translateX(" + (-size * counter ) + "px)";
}
});
Update1
CSS
*{
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.pizza-container{
width: 60%;
margin: auto;
border: 5px solid black;
overflow: hidden;
position: relative;
}
.pizza-slide {
display: flex;
width: 100%;
height: 500px;
}
#prevBtn, #nextBtn {
position: absolute;
height: 40px;
width: 40px;
top: 50%;
z-index: 10;
font-size: 20px;
color: #ffffff;
opacity: 0.8;
cursor: pointer;
background-color: #444444;
border-radius: 50%;
margin-top: -20px;
text-align: center;
line-height: 40px;
}
#prevBtn{
left: 5%;
}
#nextBtn{
right: 5%;
}
#prevBtn:hover, #nextBtn:hover{
box-shadow: 0px 0px 10px black;
background-color: #29a8e2;
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>slideshow</title>
</head>
<body>
<div class="pizza-container">
<!-- slider controls -->
<div id="prevBtn"><</div>
<div id="nextBtn">></div>
<!-- slider controls -->
<div class="pizza-slide">
<img src="./img/bilde3.jpg" id="lastClone" alt="">
<img src="./img/bilde4.jpg" alt="">
<img src="./img/bilde2.jpg" alt="">
<img src="./img/bilde3.jpg" alt="">
<img src="./img/bilde4.jpg" id="firstClone" alt="">
<!-- to get a smooth infinite loop we need to clone the last and first image-->
</div>
</div>
<script src="slideshow.js"></script>
</body>
</html>
IGNORE THIS
It looks like your post is mostly code; please add some more details.It looks like your post is mostly code; please add some more details.It looks like your post is mostly code; please add some more details.It looks like your post is mostly code; please add some more details.

The manual and your desired automatic control of the slideshow have one thing in common: both do the same thing! So instead of adding anonymous functions to the click event listeners of your buttons, let's make a function that can be called manually and automatically. In 'automatic mode' I'd rather use setTimeout instead of setInterval though. This way the function calls itself again periodically and resets the timer to the desired interval if the user pressed on one of the navigation buttons.
There's just one more problem with your code:
const size = pizzaImages[0].clientWidth;
this line gives size the value of whatever the first <img> element's width in your <div> is - which can also mean it might be 0 as the image might not be loaded yet. So let's make sure it finished loading and afterwards populate size with the correct size. Additionally this would be the perfect time to start automatic playback of your slideshow.
pizzaImages[0].addEventListener("load", function(e) {
size = e.target.clientWidth;
timer = setTimeout(nextPressed, 1500);
});
Here's the complete working example (just click on 'Run code snippet'):
const pizzaSlide = document.querySelector(".pizza-slide");
const pizzaImages = document.querySelectorAll(".pizza-slide img");
const prevBtn = document.querySelector("#prevBtn");
const nextBtn = document.querySelector("#nextBtn");
let counter = 0;
let size;
let timer;
pizzaSlide.style.transform = "translateX(" + (-size * counter) + "px)";
function nextPressed() {
if (counter >= pizzaImages.length - 1) return;
clearTimeout(timer);
timer = setTimeout(nextPressed, 1500);
pizzaSlide.style.transition = "transform 0.4s ease-in-out";
counter++;
pizzaSlide.style.transform = "translateX(" + (-size * counter) + "px)";
}
function prevPressed() {
if (counter <= 0) return;
clearTimeout(timer);
timer = setTimeout(prevPressed, 1500);
pizzaSlide.style.transition = "transform 0.4s ease-in-out";
counter--;
pizzaSlide.style.transform = "translateX(" + (-size * counter) + "px)";
}
nextBtn.addEventListener("click", nextPressed);
prevBtn.addEventListener("click", prevPressed);
pizzaSlide.addEventListener("transitionend", () => {
if (pizzaImages[counter].id === "lastClone") {
pizzaSlide.style.transition = "none";
counter = pizzaImages.length - 2;
pizzaSlide.style.transform = "translateX(" + (-size * counter) + "px)";
}
if (pizzaImages[counter].id === "firstClone") {
pizzaSlide.style.transition = "none";
counter = 1;
pizzaSlide.style.transform = "translateX(" + (-size * counter) + "px)";
}
});
pizzaImages[0].addEventListener("load", function(e) {
size = e.target.clientWidth;
timer = setTimeout(nextPressed, 1500);
});
* {
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.pizza-container {
width: 60%;
margin: auto;
border: 5px solid black;
overflow: hidden;
position: relative;
}
.pizza-slide {
display: flex;
width: 100%;
height: 500px;
}
#prevBtn,
#nextBtn {
position: absolute;
height: 40px;
width: 40px;
top: 50%;
z-index: 10;
font-size: 20px;
color: #ffffff;
opacity: 0.8;
cursor: pointer;
background-color: #444444;
border-radius: 50%;
margin-top: -20px;
text-align: center;
line-height: 40px;
}
#prevBtn {
left: 5%;
}
#nextBtn {
right: 5%;
}
#prevBtn:hover,
#nextBtn:hover {
box-shadow: 0px 0px 10px black;
background-color: #29a8e2;
}
<div class="pizza-container">
<!-- slider controls -->
<div id="prevBtn">
<</div>
<div id="nextBtn">></div>
<!-- slider controls -->
<div class="pizza-slide">
<img src="https://picsum.photos/id/1/200/300" id="lastClone" alt="">
<img src="https://picsum.photos/id/2/200/300" alt="">
<img src="https://picsum.photos/id/3/200/300" alt="">
<img src="https://picsum.photos/id/1/200/300" alt="">
<img src="https://picsum.photos/id/2/200/300" id="firstClone" alt="">
<!-- to get a smooth infinite loop we need to clone the last and first image-->
</div>
</div>

Related

Having issues on my image slider, and really not sure why

Trying to do an image slider but nothing works. I am having so much difficulty with something that everyone keeps saying pretty easy to do. I been going along with this tutorial.
https://www.youtube.com/watch?v=KcdBOoK3Pfw&list=WL&index=19&t=601s
Yet the button doesn't seem to work. The Images wont fit inside. I don't care if three of them show up at this point I just want it to work.
The images won't just go into the container. They all go in. The 2 in one wasn't my intention. I wanted one pic than the next pic shows.
I'm still pretty new to this. So probably will keep on trying and trying and understanding but trying to finish this for a personal project. Can anyone help out and explain to me what I am doing wrong.
HERE IS MY CODE:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="gallery.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="slide">
<img src="./image/pic7.jpg" id="lastClone">
<img src="image/pic1.jpg">
<img src="image/pic2.jpg">
<img src="image/pic3.jpg">
<img src="image/pic4.jpg">
<img src="image/pic6.jpg">
<img src="image/pic7.jpg">
<img src="./image/pic1.jpg" id="firstclone">
</div>
</div>
<button id="prevbtn">Prev</button>
<button id="nextbtn">Next</button>
<script src="app.js"></script>
</body>
</html>
CSS:
*{
padding:0px;
margin:0px;
box-sizing: border-box;
}
.container {
width: 40%;
margin:auto;
border: 5px solid black;
overflow:hidden;
}
.slide {
display:flex;
width:100%;
height:500px;
}
button{
padding:20px;
border:none;
background:#37f;
font-size: 30px;
color:white;
position:absolute;
top:45%;
}
#nextbtn{
border-radius: 10px 0px 0px 10px;
margin-left:950px;
}
#prevbtn{
border-radius: 0px 10px 10px 0px;
}
JAVASCRIPT:
const carouselSlide =docuement.querySelector('.slide');
const carouselImages=document.querySelectorAll('.slide img');
const prevbtn = document.querySelector('#prevbtn');
const nextbtn = document.querySelector('#nextbtn');
let counter=1;
const size=carouselImages[0].clientWidth;
carouselSlide.style.transform='translateX(' + (-size *counter) + 'px)';
nextbtn.addEventListener('click',()=>{
if (counter >= carouselImages.length-1) return;
carouselSlide.style.transition = "transform 0.4s ease-in-out";
counter ++;
carouselSlide.style.transform = 'translateX(' + (-size * counter) + 'px)';
});
prevbtn.addEventListener('click',()=>{
if (counter <= 0) return;
carouselSlide.style.transition = "transform 0.4s ease-in-out";
counter ++;
carouselSlide.style.transform = 'translateX(' + (-size * counter) + 'px)';
});
carouselSlide.addEventListener('transitionend', () => {
if (carouselImages[counter].id=='lastClone') {
carouselSlide.style.transition = "none";
counter=carouselImages.length -2;
carouselSlide.style.transform= 'translateX(' +(-size * counter) + 'px)';
}
if (carouselImaages[counter].id=='firstClone') {
carouselSlide.style.transition = "none";
counter=carouselImaages.length -counter;
carouselSlide.style.transform= 'translateX(' +(-size * counter) + 'px)';
}
});
Well right off the bat you have spaces between the counters and '++' on the event listeners, so that's not gonna work.
Some unsolicited advice: 9/10 when I was a beginner programmer it was a typo that was causing my frustrations or something missing. Before getting frustrated take a step back and look for such things.

Move an element back and forth diagonally using Java Script

I'm trying to make my div element move back and forth inside a container infinitely.
The goal is to use Java Script only, no CSS animations, jQuery, etc.
const container = document.getElementById('container');
const box = document.getElementById('box');
let t = setInterval(move, 1);
let pos = 1;
function move() {
box.style.left = pos + 'px';
box.style.top = pos + 'px';
pos++;
if (pos === 150) {
clearInterval(t)
}
}
#container{
width: 200px;
height: 200px;
background-color: green;
position: relative;
}
#box{
width: 50px;
height: 50px;
background-color: red;
position: absolute;
animation-direction: alternate;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Animation</title>
<link href="animation.css" rel="stylesheet">
<script defer src="animation.js"></script>
</head>
<body>
<div id="container">
<div id="box"></div>
</div>
</body>
</html>
So here the code. As you see, I've used position relative/absolute to make the element move with setInterval function. But when I try to reverse it back to "it's corner", it just won't work. To be honest, I've tried some stuff already, but I really can't find the solution of doing it without using any other instruments.
Thanks in advance.
You need to increase/decrease the values considering a boolean variable like below:
const container = document.getElementById('container');
const box = document.getElementById('box');
let t = setInterval(move, 1);
let pos = 1;
let test = true;
function move() {
box.style.left = pos + 'px';
box.style.top = pos + 'px';
if (test)
pos++; /* move down */
else
pos--; /* move up */
/* update the direction when you reach the top or bottom limit*/
if (pos >= 150)
test = false
else if (pos <= 0)
test = true;
}
#container {
width: 200px;
height: 200px;
background-color: green;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
}
<div id="container">
<div id="box"></div>
</div>
An alternative to get the same results
const box = document.getElementById('box');
let jump = 1;
let pos = 0;
window.setInterval(() => {
pos = pos + jump;
if (pos > 150 || pos < 0) {
jump = jump * (-1);
}
box.style.left = pos + 'px';
box.style.top = pos + 'px';
}, 1);
#container{
width: 200px;
height: 200px;
background-color: green;
position: relative;
}
#box{
width: 50px;
height: 50px;
background-color: red;
position: absolute;
animation-direction: alternate;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Animation</title>
<link href="animation.css" rel="stylesheet">
<script defer src="animation.js"></script>
</head>
<body>
<div id="container">
<div id="box"></div>
</div>
</body>
</html>

How do I fix my progress bar from glitching?

I am experiencing an issue where the progress bar is behind, if you click THIS LINK and go to the second song you will see that the progress bar is all messed up. If anyone has a solution please help! This is an image of what the problem is. Also this is all the coding I think necessary to solve the problem.
var timer;
var percent = 0;
var audio = document.getElementById("audioPlayer");
audio.addEventListener("playing", function(_event) {
var duration = _event.target.duration;
advance(duration, audio);
});
audio.addEventListener("pause", function(_event) {
clearTimeout(timer);
});
var advance = function(duration, element) {
var progress = document.getElementById("progress");
increment = 10 / duration
percent = Math.min(increment * element.currentTime * 10, 100);
progress.style.width = percent + '%'
startTimer(duration, element);
}
var startTimer = function(duration, element) {
if (percent < 100) {
timer = setTimeout(function() {
advance(duration, element)
}, 100);
}
}
#timeline {
width: 50%;
height: 4px;
background: rgba(0, 0, 0, .3);
margin-top: 27px;
float: left;
margin-left: 10px;
border-radius: 15px;
background-color: blue;
}
/*Grabable Playhead*/
#playhead {
cursor: pointer;
width: 18px;
height: 18px;
border-radius: 50%;
margin-top: -10.9px;
background: black;
}
.progress {
height: 5px;
background: black;
transition: width .1s linear;
}
<audio id="audioPlayer" preload="true" ontimeupdate="initProgressBar()">
<source src="https://tunechestmusic.000webhostapp.com/sleepy.mp3">
</audio>
<div id="wrapper">
<!--Audio Player Interface-->
<div id="audioplayer">
<button id="pButton" class="play"></button>
<div id="timeline">
<div class="progress" id="progress"></div>
<div id="playhead"></div>
</div>
</div>
</div>
It looks like you're missing some key things to make it work
The first thing is that your play button doesn't actually do anything. Try adding an event to handle the clicking of the play button and play the audio
var playButton = document.getElementById('pButton');
playButton.addEventListener('click', e => { audio.play(); });
The second issue I see is that your audio tag is supposed to call initProgressBar but that function doesn't exist.
<audio id="audioPlayer" preload="true" ontimeupdate="initProgressBar()">
I added a placeholder function for you to fill in. If you don't need this function, remove it from the HTML.
function initProgressBar() {
// TODO: What goes here?
}
After you add the click event in, the audio plays when clicked and the progress bar makes the correct progress. However, your circle doesn't move with the progress. I'm assuming you just haven't gotten that part yet.
var timer;
var percent = 0;
var audio = document.getElementById("audioPlayer");
var playButton = document.getElementById('pButton');
playButton.addEventListener('click', e => { audio.play(); });
function initProgressBar() {
// TODO: What goes here?
}
audio.addEventListener("playing", function(_event) {
var duration = _event.target.duration;
advance(duration, audio);
});
audio.addEventListener("pause", function(_event) {
clearTimeout(timer);
});
var advance = function(duration, element) {
var progress = document.getElementById("progress");
increment = 10 / duration
percent = Math.min(increment * element.currentTime * 10, 100);
progress.style.width = percent + '%'
startTimer(duration, element);
}
var startTimer = function(duration, element) {
if (percent < 100) {
timer = setTimeout(function() {
advance(duration, element)
}, 100);
}
}
#timeline {
width: 50%;
height: 4px;
background: rgba(0, 0, 0, .3);
margin-top: 27px;
float: left;
margin-left: 10px;
border-radius: 15px;
background-color: blue;
}
/*Grabable Playhead*/
#playhead {
cursor: pointer;
width: 18px;
height: 18px;
border-radius: 50%;
margin-top: -10.9px;
background: black;
}
.progress {
height: 5px;
background: black;
transition: width .1s linear;
}
<audio id="audioPlayer" preload="true" ontimeupdate="initProgressBar()">
<source src="https://tunechestmusic.000webhostapp.com/sleepy.mp3">
</audio>
<div id="wrapper">
<!--Audio Player Interface-->
<div id="audioplayer">
<button id="pButton" class="play">Play</button>
<div id="timeline">
<div class="progress" id="progress"></div>
<div id="playhead"></div>
</div>
</div>
</div>

Flickering when the dynamic change width

I want to dynamically change the width of an element. I've got working code, but it's sometimes flickering. Any idea, why?
JS:
var counter = 0;
setInterval(function() {
counter = (counter + 1) % 100;
$(".xxx").css("width", counter + "%");
}, 40);
CSS:
.xxx {
max-width: 70px;
height: 3px;
width: 0%;
background-color: orange;
}
That is how it is going to look if you try to increment 1% at a time. Rather use jquery animate to get better transition
DEMO: http://plnkr.co/edit/8OsVuRJGCLQsJWfrlzJ4
var counter =0;
setInterval(function() {
counter = (counter + 1) % 100;
$(".xxx").animate({width:counter+'px'});
}, 40);
If you want to reach a 70px width when it gets to 100%, you need to add a div parent to .xxx
like this:
<div class="yyy">
<div class="xxx"></div>
</div>
<p id="text"></p>
css:
.xxx{
height: 3px;
width: 0%;
background-color: orange;
}
.yyy{
width: 70px;
}

Loop Carousel horizontaly javascript/jquery

I was wondering if somebody could help me write a loop for this carousel? at the moment the carousel just scrolls to the right every 3 seconds then scrolls back to the left afterwards and resets itself, I would just like it to contiuously loop infinitly so it looks cleaner, could somebody point me in the right direction or help me? i know its simpler but i'm not much of a js developer! (this is for google sites html box otherwise i would have used a jquery plugin)
<style>
.carousel {
width: 1080px;
height: 220px;
position: relative;
overflow: hidden;
background-color:white;
margin-bottom: 20px;
margin-top: 20px;
margin-left: 70px;
}
.items {
width: 1080px;
position: absolute;
}
.items > div {
font-size: 20px;
display: table-cell;
vertical-align: middle;
text-align: center;
}
.items > div > img {
padding: 10px;
}
.nav {
position: absolute;
bottom: 5px;
right: 15px;
}
.button {
cursor: pointer;
font-weight: bold;
color: #fff;
}
</style>
<div class="carousel" style="display:none;">
<div class="items">
<div>
<img src="http://i59.tinypic.com/etisye.png" border="0" alt="Alkamai Logo">
</div>
<div>
<img src="http://i59.tinypic.com/ouukxu.png" border="0" alt="AWS Logo">
</div>
<div>
<img src="http://i61.tinypic.com/16k3t43.png" border="0" alt="cover-it-live">
</div>
<div>
<img src="http://i60.tinypic.com/23wljxh.png" border="0" alt="escenic">
</div>
<div>
<img src="http://i58.tinypic.com/sbiqu1.png" border="0" alt="Livefire">
</div>
<div>
<img src="http://i58.tinypic.com/do9wep.jpg" border="0" alt="ooyala">
</div>
<div>
<img src="http://i61.tinypic.com/24werue.png" border="0" alt="varnish">
</div>
<div>
<img src="http://i60.tinypic.com/2ij14rd.png" border="0" alt="wordpress">
</div>
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"> </script>
<script>
var current_slide = 0; // zero-based
var slide_count = 4;
var slide_size = 1080;
var Direction = {
LEFT: -1,
RIGHT: 1
};
/**
* Moves to the next slide using the direction (dx) parameter.
*/
var nextSlide = function(dx) {
current_slide = (current_slide + slide_count + dx) % slide_count;
// Calculate the new value for css 'left' property and animate.
var left_offset = '-' + (current_slide * slide_size) + 'px';
$('.items').animate({'left': left_offset}, 1080);
};
$('.carousel').show();
setInterval(function(){
nextSlide(Direction.RIGHT);
}, 3000);
</script>
A slight modification to your current script can make it move forward continuously.
The changes are:
current_slide is always 1 (so as to always move forward only)
When we move .items X pixels to the left, we move the corresponding number of items to the end (the number that fits inside X pixels in width)
Updated Demo: http://jsfiddle.net/techfoobar/dWy9R/4/
Code:
var parent = $('.items');
var nextSlide = function (dx) {
// NOTE: always move forward only
current_slide = 1; //(current_slide + slide_count + dx) % slide_count;
// Calculate the new value for css 'left' property and animate.
var ileft_offset = current_slide * slide_size,
left_offset = '-' + ileft_offset + 'px',
iWidth = 0;
parent.animate({
'left': left_offset
}, 'slow', function() { // called when animation is done
iWidth = parent.find('> div:first').width();
while(ileft_offset > iWidth) {
parent.find('> div:first').appendTo(parent);
ileft_offset -= iWidth;
parent.css('left', '-' + ileft_offset + 'px');
}
});
};
A modified version that doesn't pause in between. Just goes on.
Demo: http://jsfiddle.net/techfoobar/dWy9R/5/
var nextSlide = function () {
parent.animate({
'left': '-' + slide_size + 'px'
}, 4000, 'linear', function() { // called when animation is done
var ileft_offset = slide_size,
iWidth = parent.find('> div:first').width();
while(ileft_offset > iWidth) {
parent.find('> div:first').appendTo(parent);
ileft_offset -= iWidth;
parent.css('left', '-' + ileft_offset + 'px');
iWidth = parent.find('> div:first').width();
}
nextSlide();
});
};
nextSlide(); // start it off!

Categories

Resources