D. Tritonic D. Tritonic - 1 month ago 12
Javascript Question

Issues with requestAnimationFrame

I have an issue:



document.querySelector('div').addEventListener('mousedown', function(){
hello = true
document.body.addEventListener('mousemove', function(e){
if (hello) {
document.querySelector('div').style.left = (e.clientX - 12.5) + 'px'
document.querySelector('div').style.top = (e.clientY - 12.5) + 'px'
}
})
this.addEventListener('mouseup', function(e){
hello = false
posY = Math.floor(parseInt(this.style.top))
function Fall() {
posY++
document.querySelector('div').style.top = posY + 'px'
if (posY != parseInt(window.innerHeight) - 25) requestAnimationFrame(Fall)
}
Fall()
})
})

body {
margin:0;
position:absolute;
height:100vh;
width:100vw;
overflow:hidden
}

div {
position:absolute;
height:25px;
width:25px;
border:1px #000 solid;
bottom:0
}
div:hover {
cursor:pointer;
}

<div></div>





In this code (also on jsFiddle, when I drop the div, I want the div to fall, and stop at the ground.

The first time, it works. But then,
requestAnimationFrame
is faster, it's like the first one isn't done...? And after that, the div didn't stop at the ground :(

Do I have to use
setInterval
instead of
requestAnimationFrame
?

Answer Source

Whenever the div is clicked (mousedown) theres another listener assigned. When you stop clicking, these listeners are all executed in order, so at the second click, there will be two loops running, after the third there will be three loops running and so on. You may just assign the listener once:

var hello,posY;

document.querySelector('div').addEventListener('mousedown', function(){
  hello = true;
});

document.body.addEventListener('mousemove', function(e){
    if (hello) {
        document.querySelector('div').style.left = (e.clientX - 12.5) + 'px';
        document.querySelector('div').style.top = (e.clientY - 12.5) + 'px';
    }
});

document.querySelector('div').addEventListener('mouseup', function(e){
    hello = false;
    posY = Math.floor(parseInt(this.style.top));
    function Fall() {
        posY++;
        document.querySelector('div').style.top = posY + 'px';
        if (posY < parseInt(window.innerHeight) - 25) requestAnimationFrame(Fall);
    }
    Fall();
});

And please always end a statement with a semicolon...