How do I fix my progress bar from glitching? - javascript

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>

Related

Hovering on blurred video, how to unblur a part of it

After searching for a long time for an answer, here is my question:
How can I reveal a part of a html5 video that is blurred when I hover on it?
Here is some code for HTML:
<div class="container">
<video autoplay muted controls>
<source src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm">
<source src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4">
</video>
<div id="soblurme"></div>
</div>
Here is some code for CSS:
.container { position: relative; }
#soblurme {
position: absolute;
border: 1px solid white;
pointer-events: none;
width: 50px;
height: 50px;
left: 70px;
top: 20px;
/*-webkit-backdrop-filter: blur(0);*/
/*backdrop-filter: blur(0);*/
-webkit-filter: blur(0%);
filter: blur(0%);
}
video {
width: 50%;
cursor: none;
filter: blur(7px) opacity(1);
}
Here is some code for JS:
// just make the div follow the mouse
const mouse = {
x: 0,
y: 0,
dirty: false
};
const blurme = document.getElementById('soblurme');
document.querySelector('.container')
.addEventListener('mousemove', (evt) => {
mouse.x = evt.offsetX;
mouse.y = evt.offsetY;
// recently all UI events are already debounced by UAs,
// but all vendors didn't catch up yet
if( !mouse.dirty ) {
requestAnimationFrame( move );
}
mouse.dirty = true;
});
function move() {
blurme.style.left = (mouse.x - 25) + 'px';
blurme.style.top = (mouse.y - 25) + 'px';
mouse.dirty = false;
}
So, being it blurry, I would like to hover and reveal a part around the pointer so you can see through the blurred div.

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

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>

How to add a seek slider to html5 video player?

I am trying to create a custom video player, I have managed to add a seek bar now I would like to add a seek slider to my seek bar (video progress bar), meaning, I want something like this.
,
As the above image from Netflix user can slide the red circle back and force, I want the same in my custom player
Here is what I have so far.
Jsfiddle : demo
HTML
<div id="custom-seekbar">
<span></span>
</div>
<video id="video" width="400" controls autoplay>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
</video>
Js
var vid = document.getElementById("video");
vid.ontimeupdate = function(){
var percentage = ( vid.currentTime / vid.duration ) * 100;
$("#custom-seekbar span").css("width", percentage+"%");
};
$("#custom-seekbar").on("click", function(e){
var offset = $(this).offset();
var left = (e.pageX - offset.left);
var totalWidth = $("#custom-seekbar").width();
var percentage = ( left / totalWidth );
var vidTime = vid.duration * percentage;
vid.currentTime = vidTime;
});//click()
Css
#custom-seekbar
{
cursor: pointer;
height: 10px;
margin-bottom: 10px;
outline: thin solid orange;
overflow: hidden;
position: relative;
width: 400px;
}
#custom-seekbar span
{
background-color: orange;
position: absolute;
top: 0;
left: 0;
height: 10px;
width: 0px;
}
/* following rule is for hiding Stack Overflow's console */
.as-console-wrapper{ display: none !important;}
what do I need to do to achieve what I want?
try something like that.
#custom-seekbar span.hover:after{
content: '■';
display:block;
position: absolute;
background-color: red;
color: red;
top: 0;
right: 0;
}
$("#custom-seekbar").hover(function(){
$(this).find("span").addClass("hover");
}, function(){
$(this).find("span").removeClass("hover");
})
var sliderCanMove = false;
$("#custom-seekbar").on("mousedown", function(){
sliderCanMove = true;
});
$(window).on("mousemove", function(e){
if(sliderCanMove){
var offset = $("#custom-seekbar").offset();
var left = ((e.clientX + offset.left));
var totalWidth = $("#custom-seekbar").width();
var percentage = ( left / totalWidth );
var vidTime = vid.duration * percentage;
vid.currentTime = vidTime;
}
});
$(window).on("mouseup", function(){
sliderCanMove = false;
});
updated fiddle here.

Can I insert multiple setTimeouts in a setInterval?

I just started learning JavaScript and right now, I'm making a virtual traffic light that lights up red, green and orange. I would like to make a loop by adding a setInterval to the outside. Is this possible or should i use some other method of making a loop. I tried making a a for(;;){} but this causes an error and the webpage never loads. Here is my current code.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
setInterval(
setTimeout( function(){
red.style.backgroundColor = "red";
}, 2000),
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000),
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 10000),
5000);
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>
You can cal your all setTimeout function in a loop function. And call this loop function with setInterval.
Note : I also changed some of the color changing sections in your code .
jsfiddle link : https://jsfiddle.net/zgdx5xan/
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
loop();
setInterval(loop,11000);
function loop(){
console.log("loop started")
setTimeout( function(){
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
green.style.backgroundColor = "black";
console.log("red opened")
}, 2000);
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
console.log("green opened")
}, 5000);
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
red.style.backgroundColor = "black";
console.log("orange opened")
}, 10000);
}
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back{
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>
setInterval, like setTimeout also requires a function to be passed as a first argument, in that function you would then be able to compose your setTimeout's.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange');
var green = document.getElementById('circleGreens');
setInterval(function () {
red.style.backgroundColor = "black";
orange.style.backgroundColor = "black";
green.style.backgroundColor = "black";
setTimeout(function () {
red.style.backgroundColor = "red";
}, 2000);
setTimeout(function () {
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000);
setTimeout(function () {
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 8000);
}, 10000)
I have adjusted your timings a little as your final timeout was longer than the interval. You can see this working here: codepen example
Think to the traffic lights as an object with 3 states, redOn, greenOn and OrangeOn. You need to loop through states, so starting from redOn pass the next one in the sequence and reset in the last one. I think setInterval here is not required as it cause you to care about the total time that's irrelevant.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
var redFor = 200 //2000
var greenFor = 500 //5000
var orangeFor = 1000 //10000
let redOn = function(next) {
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
setTimeout(next, redFor);
}
let orangeOn = function(next) {
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
setTimeout(next, orangeFor);
}
let greenOn = function(next) {
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
setTimeout(next, greenFor);
}
let start = function() {
redOn(function() {
greenOn(function() {
orangeOn(start)
})
})
}
start()
#circleRed,
#circleGreens,
#circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body {
margin: 0;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="object2.css">
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="back">
<div id="circleRed"></div>
<div id="circleOrange"></div>
<div id="circleGreens"></div>
</div>
<script src="objects1.js"></script>
</body>
</html>
Here's an alternative implementation with equal times for every light.
var red = document.getElementById('circleRed');
var orange = document.getElementById('circleOrange');
var green = document.getElementById('circleGreens');
/* Set an array with the desired order to turn on lights */
var lights = [red, green, orange];
function open(light) {
light.classList.add('opened');
}
function close(light) {
light.classList.remove('opened');
}
function change() {
close(lights[i]);
i = (i + 1) % lights.length;
open(lights[i]);
}
/* Start */
var i = 0;
open(lights[i]);
setInterval(change, 1000);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0.2;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>
Explanation:
Instead of changing the background color of every circle from black to its own color to light up the circle or viceversa to switch off, in my example all circles have their respective color (red, green or orange) faded to (almost) transparent with opacity: 0.2 (originally I used 0, but I think it looks better with 0.2) See: opacity.
So, all elements with class .circle have:
.circle {
/* Other properties */
opacity: 0.2;
}
Then, I use a class called opened to turn the opacity to 1 making the circle visible.
.circle.opened {
opacity: 1;
}
Since .circle.opened has higher specificity than just .circle, opacity: 1 prevails on those elements having both classes (circle and opened).
To add or remove the class opened from a light item I use two simple functions open and close that manipulate the element's classList. This is important. In general it's more recommended to define element's properties (styles) in classes and use JS to add or remove this classes to alter the element that to modify element's styles directly with JS.
So, it's cleaner and more recommended to do:
/* CSS */
.red { background-color: red }
/* Javascript */
var element = document.getElementById('#element_ID');
element.classList.add('red');
than:
/* Javascript */
var element = document.getElementById('#element_ID');
element.style.backgroundColor = 'red';
Even though it may seem easier this second way.
To change the lights, I made an array with the elements in the desired order:
var lights = [red, green, orange];
As you can see, every element of the lights Array is one of the circles, we already stored in variables with document.getElementById() (if you're not familiar with arrays, dedicate some time to read and understand what they are and how they work. They're one of the most basic data structures in any programming language, so it's important to master them.)
To start, I initiate a global variable to 0 (var i = 0) and I light up the first light with:
open(lights[i]);
Since i equals 0, lights[i], so lights[0] is red (In JS, as in most languages, arrays start counting their elements from 0). This way, open(lights[i]) is the same as open(red).
Then I do a setInterval(change, 1000) so every second the function change() is called. And what does this change function do?
Basically:
// Turn off the current light
close(lights[i]);
// Increment i, so that lights[i] points to the next element...
i = (i + 1) % lights.length;
// Turn on this next element
open(lights[i]);
The rarest thing here may be the increment. Why do I do i = (i + 1) % lights.length instead of just i++.
If I do i++ after successive calls to change, i will be: 0, 1, 2, 3, 4, 5, 6... so, when I try to access lights[i] I'll get an error, because there is no element in positions 3, 4, 5... of the lights array.
I need my sequence to be: 0, 1, 2, 0, 1, 2, 0, 1, 2...
How do I get this desired sequence instead of 0, 1, 2, 3, 4, 5, 6... ?
Maybe a more understandable way could be:
i++;
if (i > 2) {
i = 0;
}
But I'm using the Remainder operator (%) to achieve the same effect.
I hope this helps!
And another one with easily configurable duration for every light:
var lights = {
red: {
node: document.getElementById('circleRed'),
duration: 4000,
},
green: {
node: document.getElementById('circleGreens'),
duration: 2000,
},
orange: {
node: document.getElementById('circleOrange'),
duration: 800,
}
};
var order = ['red', 'green', 'orange'];
function open(light) {
light.node.classList.add('opened');
}
function close(light) {
light.node.classList.remove('opened');
}
function change() {
close(lights[order[i]]);
i = (i + 1) % order.length;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
}
/* Start */
var i = 0;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>
put all setTimeout( function(){}) in one function, then it will work
Note: to make setInterval work properly, the milliseconds must be at least the total of setTimeout functions.
also you forgot to set the orange to black when the red is appearing.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
setInterval(function(){ myTimer() }, 17000);
function myTimer() {
setTimeout( function(){
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
}, 2000),
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000),
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 10000)
}
myTimer();
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>

audio pause not working, global - local variable issue?

I think I'm over-complicating things for a beginner but all I wanted to do was add addEventListener at once to four of my buttons.
Then pass on that event, to a new function which checks which button fired the event. After which, corresponding function is called for each button.
Thing goes good up until here. Everything works fine, I can even get console to log message from every function but, everything else but, audio doesn't pause.
Audio plays fine but doesn't pause, I'm thinking global - local variable issue but upon checking in DevTools, console.log says same audio is being passed to my pause function but still doesn't pause it. Didn't want to take this last resort but been working on this since yesterday, any insight would be great.
var audioBar = document.getElementsByClassName("audioBar");
var playerBtn = document.getElementsByClassName("playerBtn");
var prev = document.getElementById('prev');
var play = document.getElementById('play');
var pause = document.getElementById('pause');
var pause = document.getElementById('stop');
var next = document.getElementById('next');
var seek = document.getElementById("seek");
var eListener;
for (var i = 0; i < playerBtn.length; i++) {
playerBtn[i].addEventListener("click", whichButton, true);
eListener = playerBtn[i];
}
function whichButton(eListener) {
var whichID = eListener.target.parentElement.id;
var whichClass = eListener.target.className;
event.preventDefault();
switch (whichID) {
case "prev":
// event.preventDefault();
prevIt();
break;
case "play":
// event.preventDefault();
playIt();
break;
case "stop":
// event.preventDefault();
stopIt();
break;
case "next":
// event.preventDefault();
nextIt();
break;
default:
event.preventDefault();
}
var passenger; //Declaring passenger on global scale within whichButton
function playIt() {
// var currentSong;
function audio(src) { //constructor for audio for future efficiency
var currentSong = new Audio(src);
this.src = src;
this.play = function () {
currentSong.play();
};
this.pause = function () {
currentSong.pause();
};
this.stop = function () {
currentSong.pause();
currentSong.currentTime = 0
};
// return currentSong;
}
passenger = new audio(songs[0].file); //The passenger that's been playing around.
if (whichClass === "fa fa-play fa-2x") {
event.target.className = "fa fa-pause fa-2x";
// console.log(whichClass);
console.log("playing it");
passenger.play();
console.log(passenger); //Checking which passenger is being played
} else {
event.target.className = "fa fa-play fa-2x";
// console.log(whichClass);
console.log("pausing it"); // << This works great!
passenger.pause(); // << But this does not
}
// return passenger;
}
console.log(passenger); //Same passenger as the above one
function stopIt() {
passenger.stop(); //passing Same passenger to stop function but does not do it.
passenger.pause();
passenger.currentTime = 0;
console.log("stopping it");
}
function nextIt() {
console.log("next one");
}
}
audioPlayerContainer {
background: -webkit-linear-gradient(top, #494949 0%, #434242 31%, #393838 55%, #242323 83%, #1b1a1a 100%, #161515 100%, #0b0b0b 100%);
/*background: -webkit-linear-gradient(top, #cc4b56 0%, #c01f2c 31%, #c01f2c 55%, #c01f2c 83%, #c01f2c 100%, #ac1b27 100%, #991823 100%);*/
border: #c01f2c solid 4px;
border-top: #fff solid 1.5px;
width: 100%;
height: 50px;
position: fixed;
bottom: 0;
/*padding: 5px 50px 5px 0;*/
}
.relativeWrapper {
position: relative;
height: 100%;
box-sizing: border-box;
}
.audioBar {
display: inline-block;
background: #c01f2c;
width: 15%;
height: 100%;
font-size: 2rem;
line-height: 1rem;
text-align: center;
box-sizing: border-box;
float: left;
}
.audioBar h6 {
top:50%;
transform: translateY(-50%);
position: relative;
line-height: 1.1rem;
}
.fa-music {
font-size: 2rem;
float: left;
margin: 0 0 0 15%;
}
.aPCController {
display: inline;
float: left;
color: #f2f2f2;
margin-left: 2%;
width: 15%;
height: 35px;
/*padding-top: 0.25%;*/
top: 50%;
transform: translateY(-50%);
position: relative;
/*background: #f4c5c4;*/
}
.aPCController a {
color:#fff;
}
.aPCController a~a {
margin-left: 15px;
}
.seekWrapper {
position: relative;
float: left;
background: #2f2f2f;
height: 35px;
top: 50%;
transform: translateY(-50%);
}
.seek {
width: 55%;
/*display: inline-block;*/
}
.seekWrapper input {
/*For div*/
display: block;
font-size: 0px;
background: #c01f2c;
/*width: 50%;*/
height: 100%;
/*For input*/
-webkit-appearance: none;
width: 100%;
cursor: pointer;
}
.seekWrapper input::-webkit-slider-thumb {
-webkit-appearance: none;
border: 2px solid #000;
/*border-radius: 25%;*/
background: #fff;
width: 15px;
height: 35px;
margin-top: -1px;
}
span #title {
text-align: center;
vertical-align: middle;
color: #fff;
/*display: inline;*/
}
.vol {
width: 10%;
margin-left: 1%;
}
canvas {
top: 50%;
-webkit-box-shadow: inset 0 0 10px #000000;
box-shadow: inset 0 0 10px #000000;
}
<div class="audioPlayerContainer wrapper">
<div class="relativeWrapper">
<!--<div class="audioBar"></div>-->
<div class="audioBar">
<h6><i class="fa fa-music fa-2x"></i>audio </br> bar</h6>
</div>
<div class="aPCController"> <a class="playerBtn" id="prev" href="" title=""><i class="fa fa-step-backward fa-2x"></i></a>
<a class="playerBtn" id="play" href="" title=""><i class="fa fa-play fa-2x"></i></a>
<a class="playerBtn" id="stop" href="" title=""><i class="fa fa-stop fa-2x"></i></a>
<a class="playerBtn" id="next" href="" title=""><i class="fa fa-step-forward fa-2x"></i></a>
</div>
<!--<div id="seekWrapper"><p id="seek"><span id="title">some random title</span></p></div>-->
<div class="seekWrapper seek" id="seekWrapper">
<input type="range" id="seek" value="0" max=""><span class="_label"><p>RadioHead - Creep</p></span>
</div>
<div class="seekWrapper vol" id="volWrapper">
<input type="range" id="vol" value="0" max="10">
</div>
<!--<canvas id="previous" width="50px" height="50px" onmouseover=""></canvas>
<canvas id="play" width="50px" height="50px" onmouseover=""></canvas>
<canvas id="next" width="50px" height="50px" onmouseover=""></canvas>-->
</div>
</div>
Let me know if any other details is needed. Thanks!
Edit:
The only case where I got the passenger to stop or pause was when I passed the passenger parameter straight away to stopIt function like this, which further makes me believe this is the case of global/local variable dispute. But for a novice, I can't see anything. Researched a lot, tried a lot, still to no avail.
passenger = new audio(songs[0].file); //The passenger that's being playing around.
if (whichClass === "fa fa-play fa-2x"){
event.target.className = "fa fa-pause fa-2x";
// console.log(whichClass);
console.log("playing it");
passenger.play();
stopIt(passenger); // <<<<<Only if I do this, it stops
}
else {
event.target.className = "fa fa-play fa-2x";
// console.log(whichClass);
console.log("pausing it"); // << This works great!
passenger.pause(); // << But this does not
}
// return passenger;
}
function stopIt(stopThis){
stopThis.stop();
stopThis.pause();
stopThis.currentTime = 0;
console.log("stopping it");
}
This way it pauses/stops but it stops as soon as the passenger starts playing, without click on stop button, as the function is being called by playIt function not the click Event.
So don't know what to do.
before playing any audio/video file you have to load it first.
eg,
this.play = function(){
currentSong.load();
currentSong.play();
};
May this will solve your problem.
the main issue here is, whichButton is not the same object that is shared between the various play buttons as event listener, thus when you put the passenger outside, it would be truly global, also there were other little issues, fixed them in the demo:
fiddle demo
function whichButton(eListener) {
var whichID = eListener.target.parentElement.id;
var whichClass = eListener.target.className;
event.preventDefault();
event is undefined... This will cause javascript error.
A little late on this, but I figured I need to write what I did with this.
Like mido22 suggested, I was having troubles with my passenger, so had to change it all. I had to rewrite most of the things.
Anyways, it's pretty messy, not working on this project so didn't care for presentation. Finished this long time back but forgot to come back to stackoverflow. Came here today to seek an answer to different query.
If anyone's interested, please let me know how I can make this code better.
var audioBar = document.getElementsByClassName("audioBar"),
playerBtn = document.getElementsByClassName("playerBtn"),
prev = document.getElementById('prev'),
play = document.getElementById('play'),
pause = document.getElementById('pause'),
pause = document.getElementById('stop'),
next = document.getElementById('next'),
seek = document.getElementById("seek"),
vol = document.getElementById("vol"),
songInfo = document.getElementById("songInfo").querySelectorAll("p"),
eListener;
for(var i=0; i<playerBtn.length; i++){
playerBtn[i].addEventListener("click", whichButton, true);
eListener = playerBtn[i];
}
var audio = new Audio(),
factor = (seek.clientWidth/audio.duration) * parseFloat(audio.currentTime) / (seek.clientWidth/100);
audio.src = function (){songs[0].file};
vol.value = 5;
function progress(){
seek.value = 0;
seek.value = (seek.clientWidth/audio.duration) * parseFloat(audio.currentTime) / (seek.clientWidth/100);
songInfo[0].textContent = songs[0].artist + " - " + songs[0].title;
songInfo[1].textContent = String(audio.currentTime).toTime() + " | " + String(audio.duration).toTime();
if(audio.ended || audio.paused) {play.childNodes[0].className = "fa fa-play fa-2x";}
}
function volChange(){ vol.value = event.target.value; audio.volume = vol.value/10; }
function seekupdate(){ seek.value = event.target.value; audio.currentTime = seek.value/(seek.clientWidth/audio.duration) * (seek.clientWidth/100) }
audio.addEventListener("timeupdate", progress);
seek.addEventListener("input", seekupdate);
vol.addEventListener("input", volChange);
function whichButton(eListener){
var whichID = eListener.target.parentElement.id,
whichClass = eListener.target.className;
event.preventDefault();
if(!(audio.paused) && whichID === "stop") {audio.pause(); audio.currentTime = 0;}
if((audio.paused) && whichClass === "fa fa-play fa-2x") {audio.play(); event.target.className = "fa fa-pause fa-2x";}
if(!(audio.paused) && whichClass === "fa fa-pause fa-2x") {audio.pause(); event.target.className = "fa fa-play fa-2x";}
}

Categories

Resources