requestAnimationFrame

时间:2017-08-19 09:09:09

标签: javascript performance requestanimationframe

我有一个问题:



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>
&#13;
&#13;
&#13;

在这段代码中also on jsFiddle,当我放弃div时,我希望div掉落,然后停在地上。

第一次,它有效。但是,requestAnimationFrame更快,它就像第一个没有完成......?在那之后,div并没有停在地上:(

我是否必须使用setInterval代替requestAnimationFrame

2 个答案:

答案 0 :(得分:1)

问题是,每次 div收到mouseup时,您都会添加mousedown处理程序。您只想这样做一次,所以将其移出mousedown处理程序。因此,您在第二次调用时设置动画两次(因为两个处理程序都响应),在第三次调用时设置三次(因为所有三个处理程序都响应)等等。并且由于多个处理程序正在更新poxY,因此它不会停止在地面上,因为!=检查对除了其中一个以外的所有人都失败了。 (请参阅摘录下的进一步说明。)

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'
    }
  })
})
// Moved the below
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()
})
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 class="square"></div>

其他一些观察结果:

  • 您的代码正在成为The Horror of Implicit Globals*的牺牲品 - 声明您的变量
  • 不是一直重新查询DOM,最好先查询DOM div 一次,并在变量中记住它

* (披露:这是我贫穷的小博客上的帖子)

答案 1 :(得分:1)

每当点击div(mousedown)时,都会分配另一个侦听器。当你停止点击时,这些监听器都是按顺序执行的,所以在第二次点击时,会有两个循环运行,在第三次运行后会有三个循环运行,依此类推。您可以只分配一次监听器:

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();
});

请务必以分号结束陈述......