Javascript. Button to stop code from running - javascript

I am making little reaction game for fun as I am new to this, It's quite a big challenge, so, I ran into the problem, how do I make script to stop from running when the button is pressed, I've managed to start everything when the start is clicked, but can't stop it from running.
Maybe anyone have any ideas how to make this happen? Here's my code so far:
Here's my HTML:
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
<p>Your reaction time: <u><span id="timeTaken"></span></u></p>
<p>Your average reaction time: <u><span id="average"></span></u></p>
<p>Your best reaction time: <u><span id="best"></span></u></p>
<div id="shape"></div>
And here's my javascript:
var start = new Date().getTime();
function getRandomColor() { //generates random color
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function makeShapeAppear() { //makes that shape appear on screen
var top = Math.random() * 400;
var left = Math.random() * 400;
var width = (Math.random() * 200) + 100;
if (Math.random() > 0.5) {
document.getElementById("shape").style.borderRadius = "50%"
} else {
document.getElementById("shape").style.borderRadius = "0";
}
document.getElementById("shape").style.backgroundColor = getRandomColor();
document.getElementById("shape").style.top = top + "px";
document.getElementById("shape").style.left = left + "px";
document.getElementById("shape").style.width = width + "px";
document.getElementById("shape").style.height = width + "px";
document.getElementById("shape").style.display = "block";
start = new Date().getTime();
}
function appearAfterDelay() { //makes that shape appear after some delay
setTimeout(makeShapeAppear, Math.random() * 3000);
}
document.getElementById("reset").onclick = function() { //reset button, so when you click it, everything resets
location.reload();
}
var totaltime = 0;
var totalgames = 0;
document.getElementById("start").onclick = function() { //start button, so when you click it, shapes start appearing and time's running
appearAfterDelay();
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.display = "none";
var end = new Date().getTime();
var timeTaken = (end - start) / 1000;
totaltime += timeTaken;
totalgames += 1;
var notroundaverage = (totaltime / totalgames);
var roundaverage = notroundaverage.toFixed(3);
document.getElementById("timeTaken").innerHTML = timeTaken + " s";
document.getElementById("average").innerHTML = roundaverage + " s";
appearAfterDelay();
}
}

JavaScript is event based, and you really shouldn't attempt to 'stop' it. From looking at your code I can see that what you really want to do is clear the timeout when your button is clicked. This can be achieved by placing this line:
var timeOutId;
at the top of your code, and changing
setTimeout(makeShapeAppear, Math.random() * 3000);
to
timeOutId = setTimeout(makeShapeAppear, Math.random() * 3000);
Then, simply add a button with a click event that clears the timeout, which can be achieved using this line: window.clearTimeout(timeOutId);

Related

setInterval Mousemove trail

In my code, I wanted to create a mouse trail with 1)random images 2)a blurring effect 3) opacity transition 4) a max amount of divs in the trail.
Similar to this: https://tympanus.net/Development/ImageTrailEffects/
Point 2 and 3 are done, however I am stuck on point 4. The trail has a crazy strobe effect right now, which I dislike. I want it to be less sensitive and more subtle. Some kind of limitation on them. I've added a counter where I can count the amounts of divs created, but I'm unsure and stuck as to what to do now. I've looked at setInterval, but when I apply it to my function it's not working
I've also had some issues with the creation of an array for the random backgrounds, but I'm sure I'll figure that out. The question is mostly about how to limit and control the creation of the trail, but if anyone has a tip/link as to how to create the random background images, I am all ears.
Here the code I have up till now
window.onload= function() {
window.addEventListener('mousemove', function(e) {
var animate= function(i) {
var image= document.createElement('div'); //create a div named bubble
image.classList.add('trail');
var size= 60;
var sizepx= size+'px';
image.style.transition='2s ease';
image.style.position= 'fixed';
image.style.top= e.pageY - size/2 + 'px';
image.style.left= e.pageX - size/2 + 'px';
image.style.width= sizepx;
image.style.height= sizepx;
image.style.background= 'hsla(' +
Math.round(Math.random()*360) + ', ' +
'100%, ' +
'50%';
// image.style.background= 'black';
image.style.border= 'white 1px solid';
image.style.pointerEvents= 'none';
image.style.zIndex= 1;
document.body.appendChild(image);
//opacity and blur animations
window.setTimeout(function() {
image.style.opacity = 0;
image.style.filter = 'blur(6px)';
}, 80);
window.setTimeout(function() {
document.body.removeChild(image);
}, 2100);
};
var numItems = document.querySelectorAll('.trail').length;
console.log(numItems);
for (var i= 1; i <= 1; i+= 1) {
animate(i);
}
});
};
A fiddle:
https://jsfiddle.net/opufnsvz/
Here you go mate ( I used Unsplash for the random image source ), loading images on the fly gives unwanted effects, so they have to be preloaded. you can change the timesPerSecondto control the frequency
const numberOfImages = 10;
const imageSources = Array.from(Array(numberOfImages).keys()).map((i) => 'https://source.unsplash.com/collection/9948714?' + i);
// how many times to fire the event per second
const timesPerSecond = .1;
function preloadImages(images) {
for (i = 0; i < images.length; i++) {
let l = document.createElement('link')
l.rel = 'preload'
l.as = 'image'
l.href = images[i]
document.head.appendChild(l);
}
}
function animate(e) {
var image= document.createElement('div'); //create a div named bubble
image.classList.add('trail');
var size= 60;
var sizepx= size+'px';
image.style.transition='2s ease';
image.style.position= 'fixed';
image.style.top= e.pageY - size/2 + 'px';
image.style.left= e.pageX - size/2 + 'px';
image.style.width= sizepx;
image.style.height= sizepx;
image.style.backgroundImage = 'url(https://source.unsplash.com/collection/9948714?'+ Math.floor(Math.random()*numberOfImages) +')';
image.style.backgroundSize = 'cover';
image.style.border= 'white 1px solid';
image.style.pointerEvents= 'none';
image.style.zIndex= 1;
document.body.appendChild(image);
//opacity and blur animations
window.setTimeout(function() {
image.style.opacity = 0;
image.style.filter = 'blur(6px)';
}, 80);
window.setTimeout(function() {
document.body.removeChild(image);
}, 2100);
};
window.onload= function() {
preloadImages(imageSources);
var wait = false;
window.addEventListener('mousemove', function(e) {
if (!wait) {
wait = true;
setTimeout(() => { wait = false }, timesPerSecond * 1000);
animate(e);
}
});
};

How can i create multiple audio players(each containing different song) without copying javascript functionality?

I dont know if my title is clear enough so ill try my best to sumerize.
I created audio player containing one song using audio tag. I made all functionality in javascript for player(progress bar, volume bar, play pause stop, time etc..) and now i want to repeat same plyer in column. I copied html and everything is ok but second player with different song is not triggering javascript even though all classes are the same.
My goal is to create something similar to soundcloud website where each audio has its own audio player but i dont want to copy javascript code for every audio. Is there a way to do this using same variables?
Code is huge btw :).
HTML:
<!-- AUDIO PLAYER -->
<div class="mainPlayerDiv">
<h1>Amelie Lens - Hypnotized</h1>
<div class="mainPlayer">
<div class="audioPlayerDiv">
<div class="playPauseBtn">
<div class="btnLine"></div>
<div class="btnLine"></div>
<div class="btnLine"></div>
</div>
<div class="stopBtnDiv">
<div class="stopBtn"></div>
</div>
<i class="fas fa-volume-down volumeDownIcon"></i>
<div class="mainVolumeDiv">
<div class="volumeBar" id="volumeBar">
<div id="volume"></div>
</div>
<span id="volPercentage"></span>
</div>
<div class="trackTime">
<span id="currTime"></span> /
<span id="duration"></span>
</div>
</div>
<a class="dlLink" href="/Track/Amelie Lens - Hypnotized.mp3" download="Amelie Lens - Hypnotized">
<button class="freeDownload">
<h5>mp3</h5>
<h3>Free Download</h3>
</button>
</a>
<button class="buyTrack">
<h3>Buy This Beat</h3>
</button>
</div>
<!--<canvas id="progress" width="500" height="10"></canvas>-->
<audio id="audio" class="track" src="/Track/Amelie Lens - Hypnotized.mp3" download></audio>
<div class="progressBarCont" id="progressBarCont">
<div class="progress" id="progress"></div>
</div>
</div>
Javascript:
// AUDIO PLAYER
var audioEl = document.querySelector('.track');
audioEl.addEventListener('loadedmetadata', function(){
var duration = audioEl.duration;
var currentTime = audioEl.currentTime;
document.getElementById("duration").innerHTML = convertElapsedTime(duration);
document.getElementById("currTime").innerHTML = convertElapsedTime(currentTime);
audioEl.volume = 0.31;
document.getElementById("volPercentage").innerHTML = 30 + " %";
});
// TIME UP
audioEl.addEventListener("timeupdate", function(){
var timeline = document.getElementById("currTime");
var s = parseInt(audioEl.currentTime % 60);
var m = parseInt((audioEl.currentTime / 60) % 60);
if (s < 10) {
timeline.innerHTML = m + ':0' +s;
} else {
timeline.innerHTML = m + ':' +s;
}
if (audioEl.ended) {
playPauseBtn.classList.remove('transform');
stopBtnDiv.classList.add('transform');
audioEl.currentTime = 0;
percent = 0;
progress.style.width = '0';
stopped = true;
clearInterval(interval);
clearInterval(interval2);
audioPlayerDiv.classList.remove('playAnimation');
audioPlayerDiv.classList.remove('playAnimation2');
}
}, false);
// OVERALL DURATION
function convertElapsedTime(inputSeconds) {
var seconds = Math.floor(inputSeconds % 60);
if (seconds < 10) {
seconds = "0" + seconds;
}
var minutes = Math.floor(inputSeconds / 60);
return minutes + ":" + seconds;
}
// PROGRESS BAR
var timer;
var percent = 0;
var audioEl = document.getElementById("audio");
audioEl.addEventListener("playing", function(_event) {
var duration = _event.target.duration;
advance(duration, audioEl);
});
audioEl.addEventListener("pause", function(_event) {
var progress = document.getElementById("progress");
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);
}
}
// PROGRESS BAR SEEK
var progressBarCont = document.getElementById('progressBarCont');
var progress = document.getElementById("progress");
progressBarCont.addEventListener("mousedown", function(event){
var viewportset = progressBarCont.getBoundingClientRect();
var clickedPos = event.clientX - viewportset.left;
audioEl.currentTime = (clickedPos / event.target.offsetWidth) * audioEl.duration;
}, false);
// PROGRESS BAR END
/*
VOLUME SLIDER
*/
var volumeSlider = document.getElementById("volume");
var volumeBar = document.getElementById("volumeBar");
volumeBar.addEventListener('click', function(e){
var viewportOffset = volumeBar.getBoundingClientRect();
var cursorPosition;
cursorPosition = Math.floor(e.clientX - viewportOffset.left);
if(cursorPosition <= 9) {
audioEl.volume = '0.0' + cursorPosition;
document.getElementById("volPercentage").innerHTML = cursorPosition + " %";
volumeSlider.style.width = cursorPosition + "px";
} else if (cursorPosition === 100) {
audioEl.volume = 1;
document.getElementById("volPercentage").innerHTML = cursorPosition + " %";
volumeSlider.style.width = cursorPosition + "px";
} else {
audioEl.volume = '0.' + cursorPosition;
document.getElementById("volPercentage").innerHTML = cursorPosition + " %";
volumeSlider.style.width = cursorPosition + "px";
}
if(cursorPosition >= 50) {
volumeIconBtn.classList.remove('.fas');
volumeIconBtn.classList.remove('fa-volume-mute');
volumeIconBtn.classList.add('.fas');
volumeIconBtn.classList.add('fa-volume-up');
audioDownUp = 2;
} else {
volumeIconBtn.classList.remove('.fas');
volumeIconBtn.classList.remove('fa-volume-up');
}
if (cursorPosition <= 49) {
volumeIconBtn.classList.remove('.fas');
volumeIconBtn.classList.remove('fa-volume-mute');
volumeIconBtn.classList.add('.fas');
volumeIconBtn.classList.add('fa-volume-down');
audioDownUp = 1;
} else {
volumeIconBtn.classList.remove('.fas');
volumeIconBtn.classList.remove('fa-volume-down');
}
volPercentage.classList.add('showVolPercent');
setTimeout(function(){
volPercentage.classList.remove('showVolPercent');
}, 5000);
});
///////////////////// VOLUME SLIDER END
const playPauseBtn = document.querySelector('.playPauseBtn');
const stopBtnDiv = document.querySelector('.stopBtnDiv');
const stopBtn = document.querySelector('.stopBtn');
playPauseBtn.addEventListener('click', playPauseFunction);
stopBtnDiv.addEventListener('click', stopFunction);
let stopped = true;
var interval;
var interval2;
function playPauseFunction() {
if(audioEl.paused) {
playPauseBtn.classList.add('transform');
playPauseBtn.classList.add('transform2');
setTimeout(function(){
playPauseBtn.classList.remove('transform2');
}, 200);
audioEl.play();
audioEl2.play();
stopped = false;
let animation = 1;
interval = setInterval(function() {
if(animation === 1) {
audioPlayerDiv.classList.add('playAnimation');
animation = 0;
} else {
audioPlayerDiv.classList.remove('playAnimation');
animation = 1;
}
},16000);
let animation2 = 1;
interval2 = setInterval(function() {
if(animation2 === 1) {
audioPlayerDiv.classList.add('playAnimation2');
animation2 = 0;
} else {
audioPlayerDiv.classList.remove('playAnimation2');
animation2 = 1;
}
},32000);
} else {
playPauseBtn.classList.remove('transform');
playPauseBtn.classList.add('transform2');
setTimeout(function(){
playPauseBtn.classList.remove('transform2');
}, 200);
audioEl.pause();
stopped = false;
clearInterval(interval);
clearInterval(interval2);
audioPlayerDiv.classList.remove('playAnimation');
audioPlayerDiv.classList.remove('playAnimation2');
}
}
function stopFunction() {
if(!audioEl.paused) { // IF PLAYING
playPauseBtn.classList.remove('transform');
stopBtnDiv.classList.add('transform2');
stopBtnDiv.classList.add('transform');
setTimeout(function(){
stopBtnDiv.classList.remove('transform');
stopBtnDiv.classList.remove('transform2');
}, 200);
clearInterval(interval);
clearInterval(interval2);
audioPlayerDiv.classList.remove('playAnimation');
audioPlayerDiv.classList.remove('playAnimation2');
audioEl.currentTime = 0;
percent = 0;
progress.style.width = '0';
stopped = true;
audioEl.pause();
} else if (audioEl.paused && !stopped) {
stopBtnDiv.classList.add('transform');
stopBtnDiv.classList.add('transform2');
setTimeout(function(){
stopBtnDiv.classList.remove('transform');
stopBtnDiv.classList.remove('transform2');
}, 200);
clearInterval(interval);
clearInterval(interval2);
audioPlayerDiv.classList.remove('playAnimation');
audioPlayerDiv.classList.remove('playAnimation2');
audioEl.currentTime = 0;
percent = 0;
progress.style.width = '0';
stopped = true;
} else if (stopped){
audioEl.currentTime = 0;
percent = 0;
progress.style.width = '0';
stopped = true;
}
}
here's ss of players
Many thanks in advance.
You could use the Audio() constructor.
const player = (audiofile) => {
const newPlayer = new Audio(audiofile)
return newPlayer
}
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement
Then create a new player by calling player('audio.wav')
ADDED:
Now that I can see your code, the other way to create many players dynamically is:
Create an array for your audio files:
const tracks = ['track1.wav', 'track2.wav']
Add a container for your players in your HTML
<div id="players"></div>
Add a function that creates a player and appends it to the container dynamically
const players = document.getElementById('players')
const player = (audiofile) => {
const newPlayer = document.createElement('audio')
audio.src = audiofile
// anything else you want to add
}
players.appendChild(newPlayer)
}
The audio() constructor and createElement(audio) both create new audio element, but audio() does not interact with the DOM.
Lastly, you would have to create a function that renders as many players as there are tracks.
Once you have rendered the players successfully, you should add an event listener for you controls so that the correct audio is played when user clicks on play etc.
https://developer.mozilla.org/en-US/docs/Web/API/Event/target

Why won't this clearInterval work?

I'm making a race where two images move to the right a random number of px's but they won't stop with the clear interval, the alert "stop" works. I'm using a red and green picture with changing z-indexes like a stoplight for the user to start and stop the race.
<script type="text/javascript">
var ship = 0;
var ufo = 0;
function random()
{
var rand = Math.floor((Math.random() * 15) + 1);
var rand2 = Math.floor((Math.random() * 15) + 1);
ship = ship + rand;
ufo = ufo + rand2;
document.getElementById("ufo").style.left = ufo + 'px';
document.getElementById("spaceship").style.left = ship + 'px';
}
function start()
{
if(document.getElementById("red").style.zIndex == 1)
{
document.getElementById("red").style.zIndex = "0";
alert("go");
var timer = setInterval(function() {random()},1000);
}
else
{
document.getElementById("green").style.zIndex = "0";
document.getElementById("red").style.zIndex = "1";
clearInterval(timer);
alert("stop");
}
}
</script>
Because var timer only exists within the if statement. You need to move it outside of the start() function, like this:
var timer;
function start()
{
if(document.getElementById("red").style.zIndex == 1)
{
document.getElementById("red").style.zIndex = "0";
alert("go");
timer = setInterval(function() {random()},1000);
}
else
{
document.getElementById("green").style.zIndex = "0";
document.getElementById("red").style.zIndex = "1";
clearInterval(timer);
alert("stop");
}
}

How to play/pause a JavaScript onClick event?

As I'm a JavaScript beginner, I wish to know how could I Play and Pause a JavaScript on an html page.
On the first JavaScript file I have a toggle button that onClick show/hide a div element tag, like this:
$(function () {
$(".toggleSidebar").click(function(event) {
$(".sidebarToggle").hide();
$(".toggleSidebar").removeClass("btn-info");
$(this).addClass("btn-info");
$("#"+$(this).attr("data-target")).fadeIn(500);
localStorage.tab_sidebar = $(this).attr("data-target")
});
if(localStorage.tab_sidebar != '')
{
$('.toggleSidebar[data-target="'+localStorage.tab_sidebar+'"]').click();
}
});
function toggleSidebar()
{
if ($("#my-section").hasClass('hide'))
$("#my-section").removeClass('hide');
else
$("#my-section").addClass('hide');
}
The div tag element has this JavaScript for the animation of the background:
var colors = new Array(
[62,35,255],
[60,255,60],
[255,35,98],
[45,175,230],
[255,0,255],
[255,128,0]);
var step = 0;
var colorIndices = [0,1,2,3];
//transition speed
var gradientSpeed = 0.0002;
function updateGradient()
{
if ( $===undefined ) return;
var c0_0 = colors[colorIndices[0]];
var c0_1 = colors[colorIndices[1]];
var c1_0 = colors[colorIndices[2]];
var c1_1 = colors[colorIndices[3]];
var istep = 1 - step;
var r1 = Math.round(istep * c0_0[0] + step * c0_1[0]);
var g1 = Math.round(istep * c0_0[1] + step * c0_1[1]);
var b1 = Math.round(istep * c0_0[2] + step * c0_1[2]);
var color1 = "rgb("+r1+","+g1+","+b1+")";
var r2 = Math.round(istep * c1_0[0] + step * c1_1[0]);
var g2 = Math.round(istep * c1_0[1] + step * c1_1[1]);
var b2 = Math.round(istep * c1_0[2] + step * c1_1[2]);
var color2 = "rgba("+r2+","+g2+","+b2+")";
$('#my-section').css({
background: "-webkit-gradient(linear, left top, right top, from("+color1+"), to("+color2+"))"}).css({
background: "-moz-linear-gradient(left, "+color1+" 0%, "+color2+" 100%)"});
step += gradientSpeed;
if ( step >= 1 )
{
step %= 1;
colorIndices[0] = colorIndices[1];
colorIndices[2] = colorIndices[3];
//pick two new target color indices
//do not pick the same as the current one
colorIndices[1] = ( colorIndices[1] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
colorIndices[3] = ( colorIndices[3] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
}
}
setInterval(updateGradient,10);
The problem is that this JavaScript runs continuosly also when the row is hidden, wasting PC resources.
So how could I make this JavaScript goes on play (when row is shown) and pause (when row is hidden) every time I press my toggle button?
var colors = ...;
// All variable declarations for animated background
function updateGradient() {
// Update gradient function (unchanged)
}
var refreshIntervalId;
// Or var refreshIntervalId = setInterval(updateGradient, 10);
// If you want the updateGradient function to run by default when the page is open.
function toggleSidebar() {
if($("#my-section").hasClass('hide')) {
// Show sidebar
$("#my-section").removeClass('hide');
// Loops updateGradient function
refreshIntervalId = setInterval(updateGradient, 10);
} else {
// Hide sidebar
$("#my-section").addClass('hide');
// Stops updateGradient function
clearInterval(refreshIntervalId);
}
}

change an image onload

I have a simple webpage with an image in a div on the homepage and would like to use javascript to change the image for an alternative image after the page has loaded (only once) using a slow fade, i am currently using an animated gif to do this but would prefer to use javascript.
I have limited javascript skills.
thanks
I'm assuming that you won't use jQuery so i've created simple js eample which fades out one image and fades in other after page is loaded. You can check the example here http://jsfiddle.net/rJzPV/7/
function fadeOut(elem, time, callbackFn) {
var startOpacity = elem.style.opacity || 1;
elem.style.opacity = startOpacity;
(function go() {
elem.style.opacity -= startOpacity / (time / 100);
// for IE
elem.style.filter = 'alpha(opacity=' + elem.style.opacity * 100 + ')';
if (elem.style.opacity > 0.11)
setTimeout(go, 100);
else {
elem.style.display = 'none';
if (callbackFn)
callbackFn();
}
})();
}
function fadeIn(elem, time) {
var startOpacity = 0.1;
elem.style.opacity = startOpacity;
elem.style.display = "";
(function go() {
elem.style.opacity -= -startOpacity / (time / 1000);
// for IE
elem.style.filter = 'alpha(opacity=' + elem.style.opacity * 100 + ')';
if (elem.style.opacity < 1)
setTimeout(go, 100);
})();
}
window.addEvent('load', function () {
function changePicture() {
var _myImg = document.getElementById("myImage");
_myImg.src = "http://www.google.com/logos/2012/klimt12-hp.jpg";
fadeIn(_myImg, 1000);
}
var _myImg = document.getElementById("myImage");
fadeOut(_myImg, 1000, changePicture);
});

Categories

Resources