setInterval() only fires once - javascript
var x = 0;
window.addEventListener("keydown", function(e) {
switch (e.key) {
case "ArrowLeft":
setInterval(changeValue, 1000, "up");
break;
case "ArrowRight":
setInterval(changeValue, 1000, "down");
break;
}
})
function changeValue(direction) {
switch (direction) {
case "up":
x += 10;
console.log(x);
break;
case "down":
x -= 10;
console.log(x);
break;
}
}
I was expecting my code to keep adding or subtracting 10 from x every second depending on what arrow key the user has pressed. However, setInterval only seems to fire once, and I can't figure out why.
A way to do what you are looking for:
var
conterVal = 0
, addValue = -10
, refIntv = null
;
bt_tenMoreLess.onclick =_=>
{
addValue = -addValue
if (!refIntv)
{
counter.textContent = conterVal += addValue
refIntv = setInterval( changeValue , 1000)
bt_stop.disabled = false
}
}
bt_stop.onclick =_=>
{
clearInterval( refIntv )
refIntv = null
bt_stop.disabled = true
}
function changeValue()
{ counter.textContent = conterVal += addValue }
<p id="counter">0</p>
<button id="bt_tenMoreLess">count ± 10</button>
<button id="bt_stop" disabled >stop</button>
Related
How to put an interval inside a switch case statment of keycode without allowing the user to tab twice
Im building a pacman game and i put a switch statement and put interval so that the user has to press right arrow once and pacman will keep moving right the problem is that if i tab twice it move twice as fast and i tab right then left it'll move right left right left..... i'll show the first code where there was no problem this code is without interval JS code without interval: const grid = document.querySelector('.grid'); const scoreEl = document.getElementById('score'); const width = 28; let squares = []; let score = 0; const layout = [ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, 1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1, 1,3,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,3,1, 1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1, 1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1, 1,1,1,1,1,1,0,1,1,4,4,4,4,4,4,4,4,4,4,1,1,0,1,1,1,1,1,1, 1,1,1,1,1,1,0,1,1,4,1,1,1,2,2,1,1,1,4,1,1,0,1,1,1,1,1,1, 1,1,1,1,1,1,0,1,1,4,1,2,2,2,2,2,2,1,4,1,1,0,1,1,1,1,1,1, 4,4,4,4,4,4,0,0,0,4,1,2,2,2,2,2,2,1,4,0,0,0,4,4,4,4,4,4, 1,1,1,1,1,1,0,1,1,4,1,2,2,2,2,2,2,1,4,1,1,0,1,1,1,1,1,1, 1,1,1,1,1,1,0,1,1,4,1,1,1,1,1,1,1,1,4,1,1,0,1,1,1,1,1,1, 1,1,1,1,1,1,0,1,1,4,1,1,1,1,1,1,1,1,4,1,1,0,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,1, 1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1, 1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1, 1,3,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,3,1, 1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1, 1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1, 1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1, 1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1, 1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]; // 0 - pacdots // 1 - wall // 2 - ghost lair // 3 - powerpellets // 4 - empty function createBoard() { for (let i = 0; i < layout.length; i++) { const square = document.createElement('div'); grid.appendChild(square); squares.push(square); if (layout[i] === 0) { squares[i].classList.add('pac-dot'); } else if (layout[i] === 1) { squares[i].classList.add('wall'); } else if (layout[i] === 2) { squares[i].classList.add('ghost-lair'); } else if (layout[i] === 3) { squares[i].classList.add('power-pallets'); } } } createBoard(); let pacManPosition = 490; squares[pacManPosition].classList.add('pac-man'); function move(e) { squares[pacManPosition].classList.remove('pac-man'); //console.log(e.key) //fix all these cases switch (e.key) { case 'ArrowUp': if (!squares[pacManPosition - width].classList.contains('wall')) { pacManPosition -= width; } break; case 'ArrowRight': if (!squares[pacManPosition + 1].classList.contains('wall')) { pacManPosition++; } break; case 'ArrowDown': console.log('DOWN'); if (!squares[pacManPosition + width].classList.contains('wall')) { pacManPosition += width; } break; case 'ArrowLeft': if (!squares[pacManPosition - 1].classList.contains('wall')) { pacManPosition--; } break; } squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } document.addEventListener('keyup', move); JS Code with intervals: // let myInt = ''; // function move(e) { squares[pacManPosition].classList.remove('pac-man'); //console.log(e.key) //fix all these cases switch (e.key) { case 'ArrowUp': myInt = setInterval( function () { //console.log('up') if (!squares[pacManPosition - width].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition -= width; squares[pacManPosition].classList.add('pac-man'); } }, 400) break; case 'ArrowRight': myInt = setInterval( function () { //console.log('up') if (!squares[pacManPosition + 1].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition++; squares[pacManPosition].classList.add('pac-man'); } }, 400) break; case 'ArrowDown': console.log('DOWN'); myInt = setInterval( function () { //console.log('up') if (!squares[pacManPosition + width].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition += width; squares[pacManPosition].classList.add('pac-man'); } }, 400) break; case 'ArrowLeft': myInt = setInterval( function () { //console.log('up') if (!squares[pacManPosition - 1].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition--; squares[pacManPosition].classList.add('pac-man'); } }, 400) break; } squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } how can i fix this?
some guy answered as a comment that i should clear the inteval on each key pressed. i don't know why i haven't thought about that the answer : case 'ArrowUp': clearInterval(myInt); myInt = setInterval( function () { //console.log('up') if (!squares[pacManPosition - width].classList.contains('wall')) { powerPelletsEaten(); squares[pacManPosition].classList.remove('pac-man'); pacManPosition -= width; squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); } }, 400) break;
Disable keyboard in javascript
I'm trying to figure out how to make the keyboard get disabled after the score equals five. with everything else I'm fine. I got everything else done that I need to get done I'm just having issues with the keyboard, if I could get some help on this it would greatly be appreciated. this is just giving me a hard time so I thought I would get some help. //Arrow key codes var UP = 38; var DOWN = 40; var RIGHT = 39; var LEFT = 37; //Directions var moveUp = false; var moveDown = false; var moveRight = false; var moveLeft = false; //Add keyboard listeners window.addEventListener("keydown", function(event) { switch(event.keyCode) { case UP: moveUp = true; break; case DOWN: moveDown = true; break; case LEFT: moveLeft = true; break; case RIGHT: moveRight = true; break; } }, false); window.addEventListener("keyup", function(event) { switch(event.keyCode) { case UP: moveUp = false; break; case DOWN: moveDown = false; break; case LEFT: moveLeft = false; break; case RIGHT: moveRight = false; break; } }, false); function loadHandler() { update(); } function update() { //The animation loop requestAnimationFrame(update, canvas); //Up if(moveUp && !moveDown) { cat.vy = -5; } //Down if(moveDown && !moveUp) { cat.vy = 5; } //Left if(moveLeft && !moveRight) { cat.vx = -5; } //Right if(moveRight && !moveLeft) { cat.vx = 5; } //Set the cat's velocity to zero if none of the keys are being pressed if(!moveUp && !moveDown) { cat.vy = 0; } if(!moveLeft && !moveRight) { cat.vx = 0; } //Move the cat cat.x += cat.vx; cat.y += cat.vy; //Check for a collision between the cat and the monster //and change the monster's score when they collide if(hitTestRectangle(cat, monster) && score < 5) { if(!collisionHasOccured) { score++; collisionHasOccured = true; } } else { collisionHasOccured = false; } if(score === 5) { message = " - Game Over!"; } //Render the sprites render(); } function hitTestRectangle(r1, r2) { //A variable to determine whether there's a collision var hit = false; //Calculate the distance vector var vx = r1.centerX() - r2.centerX(); var vy = r1.centerY() - r2.centerY(); //Figure out the combined half-widths and half-heights var combinedHalfWidths = r1.halfWidth() + r2.halfWidth(); var combinedHalfHeights = r1.halfHeight() + r2.halfHeight(); //Check for a collision on the x axis if(Math.abs(vx) < combinedHalfWidths) { //A collision might be occuring. //Check for a collision on the y axis if(Math.abs(vy) < combinedHalfHeights) { //There's definitely a collision happening hit = true; } else { //There's no collision on the y axis hit = false; } } else { //There's no collision on the x axis hit = false; } return hit; } function render(event) { drawingSurface.clearRect(0, 0, canvas.width, canvas.height); if(sprites.length !== 0) { for(var i = 0; i < sprites.length; i++) { var sprite = sprites[i]; drawingSurface.drawImage ( image, sprite.sourceX, sprite.sourceY, sprite.sourceWidth, sprite.sourceHeight, Math.floor(sprite.x), Math.floor(sprite.y), sprite.width, sprite.height ); } } drawingSurface.fillText(score + message, monster.x, monster.y - 40); } </script>
You just need to add an if statement to your event listeners. ( IF score == 5 ) then don't do anything. You can place the code right above the switch statements. EDIT #JasonEnts: window.addEventListener("keydown", function(event) { if (score < 5) { switch(event.keyCode) { case UP: moveUp = true; break; case DOWN: moveDown = true; break; case LEFT: moveLeft = true; break; case RIGHT: moveRight = true; break; } } }, false);
How can I make box transition only for horizontal and vertical?
I'm trying to make a box moving by horizontal and vertical on the arrows press. But when I pres for example up arrow and right arrow it goes by diagonal. Here is my codepen .box { background-color: gray; height: 100px; width: 100px; transition: margin 0.5s cubic-bezier(0, .7, 0, 1); } const box = document.getElementsByClassName('box')[0]; document.addEventListener('keydown', function({keyCode, which}) { const keycode = keyCode ? keyCode : which, startValue = '0px', shiftValue = '400px'; console.log(box.style.marginLeft, box.style.marginTop) switch(keycode) { case(40): box.style.marginTop = shiftValue; break; case(39): box.style.marginLeft = shiftValue; break; case(38): box.style.marginTop = startValue; break; case(37): box.style.marginLeft = startValue; break; } });
Try the following: const box = document.getElementsByClassName('box')[0]; let moving = false; document.addEventListener('keydown', function({keyCode, which}) { const keycode = keyCode ? keyCode : which, startValue = '0px', shiftValue = '400px'; console.log(box.style.marginLeft, box.style.marginTop) if (!moving && [37, 38, 39, 40].includes(keycode)){ switch(keycode) { case(40): box.style.marginTop = shiftValue; break; case(39): box.style.marginLeft = shiftValue; break; case(38): box.style.marginTop = startValue; break; case(37): box.style.marginLeft = startValue; break; } moving = true; window.setTimeout(() => moving = false, 400); // Not 500, because visually it is very slow towards the end anyway. } });
Either you could implement a Promise solution in here but I don't think it's worth justifying. Basically what we can do is to store all the keys pressed in an array and make sure the javascript only goes through the array of pressed keys once every x milliseconds. const box = document.getElementsByClassName('box')[0]; let pressedKeys = []; let timeoutHandler = -1; document.addEventListener('keydown', function({keyCode, which}) { // As soon as the user presses a key we will clear the time out clearTimeout(timeoutHandler); const keycode = keyCode ? keyCode : which, startValue = '0px', shiftValue = '400px'; pressedKeys.push(keycode); // register the timeout to a variable in order for this function // only run once every x second. This implementation is also // known as 'debounce function to poor people' timeoutHandler = setTimeout(() => { pressedKeys.forEach((key, index) => { // The animation time for each key pressed will be incremental // which means the second key pressed will have an animation delay // higher than the first one const timeoutSeconds = index === 0 ? 1 : index + (index * 100); setTimeout(() => { switch(key) { case(40): box.style.marginTop = shiftValue; break; case(39): box.style.marginLeft = shiftValue; break; case(38): box.style.marginTop = startValue; break; case(37): box.style.marginLeft = startValue; break; } }, timeoutSeconds) }); pressedKeys = []; }, 100) });
One possible solution: you could keep track of which moves have been requested and wait to perform the move until the previous move has finished. Example: const box = document.getElementsByClassName('box')[0]; const startValue = '0px'; const shiftValue = '400px'; function moveDown() { // The move* functions only perform the move if is valid - i.e., // if it would actually cause a visible change. if (box.style.marginTop !== shiftValue) { box.style.marginTop = shiftValue; return true; } // The move* functions return true iff the move was made. return false; } function moveRight() { if (box.style.marginLeft !== shiftValue) { box.style.marginLeft = shiftValue; return true; } return false; } function moveUp() { if (box.style.marginTop !== startValue) { box.style.marginTop = startValue; return true; } return false; } function moveLeft() { if (box.style.marginLeft !== startValue) { box.style.marginLeft = startValue; return true; } return false; } const moves = []; let timeOfLastMoveInMilliseconds = null; const animationDurationInSeconds = 0.5; // should match css transition duration const animationDurationInMilliseconds = animationDurationInSeconds * 1000; function onFrame() { if (!timeOfLastMoveInMilliseconds) { timeOfLastMoveInMilliseconds = performance.now(); } const timeSinceLastMove = performance.now() - timeOfLastMoveInMilliseconds; if (moves.length > 0 && timeSinceLastMove >= animationDurationInMilliseconds) { const wasMoved = moves.pop()(); if (wasMoved) { timeOfLastMoveInMilliseconds = performance.now(); } } window.requestAnimationFrame(onFrame); } window.requestAnimationFrame(onFrame); document.addEventListener('keydown', function({keyCode, which}) { const keycode = keyCode ? keyCode : which; switch(keycode) { case(40): moves.unshift(moveDown); break; case(39): moves.unshift(moveRight); break; case(38): moves.unshift(moveUp); break; case(37): moves.unshift(moveLeft); break; } }); Note that the code above keeps track of every move the user makes, so, e.g., if you press down, up, down, up, down quickly, that sequence will play back. Depending on your application, you might want to add restrictions so that, e.g., only horizontal+diagonal moves are allowed and/or only moves coming from keypresses that happen within a short timeframe.
So, I decided to set 500 milliseconds breaks between every press on the key with animation and if it's faster without animation, but without any additional asynchronous code. Thanks for the help. .box { background-color: gray; height: 100px; width: 100px; } .animation { transition: margin 0.5s cubic-bezier(0, .7, 0, 1); } const box = document.getElementsByClassName('box')[0]; let prevTime = 0; document.addEventListener('keydown', function({keyCode, which}) { const keycode = keyCode ? keyCode : which, startValue = '0px', shiftValue = '400px', currentTime = Date.now(); let diff = 0; diff = currentTime - prevTime; if (diff > 500) { box.classList.add('animation'); } else { box.classList.remove('animation'); } switch(keycode) { case(40): box.style.marginTop = shiftValue; break; case(39): box.style.marginLeft = shiftValue; break; case(38): box.style.marginTop = startValue; break; case(37): box.style.marginLeft = startValue; break; } prevTime = currentTime; });
Clear interval not working on javascript timer
Here is my code document.addEventListener("keydown", move); function move(e) { switch (e.keyCode) { case 37: x = x - speed; break; case 38: // up key pressed y = y - speed break; case 39: x = x + speed break; case 40: y = y + speed break; case 32: if (iTouched == true) { startCounter(); } break; } sendData(); } document.addEventListener("keyup", getStuff); function getStuff(e) { switch (e.keyCode) { case 32: if (iTouched == true) { shoot(); } break; } } function startCounter() { function count() { time += 1 console.log(time) } interval = setInterval(count, 100) } function shoot() { clearInterval(interval) } The startCounter() function is triggered by a keydown event listener and the shoot() function is triggered by a keyup event listener. For some reason the setInterval will not stop when I lift the key up. The shoot() function works with other commands like an alert() just not the clearInterval(). Am I doing something wrong? Thanks!
Keydown fires multiple times as you hold down the key. var bod = document.body; bod.addEventListener("keydown", () => console.log('keydown', new Date())) bod.addEventListener("keyup", () => console.log('keyup', new Date())) So you create more than one interval so you overwrite the last one. So you need to clear the interval before you create a new one if (interval) clearInterval(interval) interval = setInterval(count, 100) or do not create one if it exists if (!interval) { interval = setInterval(count, 100) } and when you clear it function shoot() { clearInterval(interval) interval = null }
Jquery: count using setInterval
Im trying to create two counter when I press downKey I want to counter1 start counting and when I press keyLeft I want to stop the first counter and start counter2 .... I know that I need to use clearInterval() function but I dont know where I need to use it, here is a JSFiddle to see what I mean html: <div id="left"></div> <div id="down"></div> js: $('body').keydown(function (e) { switch (e.which) { case 39: clearInterval(down_move); var i=0; var right_move = setInterval(function(){ $('#left').html(i); i++ }, 1000) break; case 40: clearInterval(right_move); var j = 0; var down_move = setInterval(function(){ $('#down').html(j) j++; }, 1000); break; default: } e.preventDefault(); });
You need to declare down_move and right_move outside of keydown: var right_move, down_move; $('body').keydown(function (e) { switch (e.which) { case 39: clearInterval(down_move); var i=0; right_move = setInterval(function(){ $('#left').html(i); i++ }, 1000) break; case 40: clearInterval(right_move); var j = 0; down_move = setInterval(function(){ $('#down').html(j) j++; }, 1000); break; default: } e.preventDefault(); });
it seems like a scope issue, here is how I would make it: updated fiddle var Interval = function(intervalFunc, selector){ var interval; this.start = function(){ interval = setInterval(intervalFunc, 1000); }, this.stop = function(){ clearInterval(interval); } } var i = 0; var rightBtnInterval = new Interval(function downInterval(){ $('#right').html(i) i++; }); var j = 0; var downBtnInterval = new Interval(function downInterval(){ $('#down').html(j) j++; }); $('body').keydown(function (e) { switch (e.which) { case 39: rightBtnInterval.stop(); downBtnInterval.start(); break; case 40: downBtnInterval.stop(); rightBtnInterval.start(); break; default: } e.preventDefault(); });
You have to store outside of function the interval to stop. Warning the ascii code of left is 37. Here is a JSFiddle to see my change: var storeInterval = null; $('body').keydown(function (e) { switch (e.which) { case 37: clearInterval(storeInterval); var i=0; storeInterval = setInterval(function(){ $('#left').html(i); i++ }, 1000) break; case 40: clearInterval(storeInterval); var j = 0; storeInterval = setInterval(function(){ $('#down').html(j) j++; }, 1000); break; default: } e.preventDefault(); }); <div id="left"></div> <div id="down"></div>