我一直在使用以下简单代码在屏幕上拖动固定位置分区。它可以工作,但是响应速度不如拖动浏览器弹出窗口(例如“打开文件”窗口)时那样。
如您所见,除了修改包含元素的顶部和左侧位置的样式之外,mousemove事件处理程序内部几乎没有发生任何事情。如果从最边缘拖动元素,则鼠标将保持在元素前方约半英寸处,特别是在以缓慢到中等的速度移动时,这与浏览器弹出式窗口会紧贴鼠标指针保持一致。
我尝试将元素位置更新与mousemove事件分离,并在单独的函数中使用requestAnimationFrame来更新元素位置;响应能力也不会更好,甚至可能会更差。该代码还在函数名称中带有_rAF后缀。
这两个版本的代码中是否都存在问题,这是一种更好的方法,还是这是浏览器中拖动事件的最佳选择?
This问题有点相似,我阅读了它提供给HTML5 Rocks网站的链接;这就是为什么我尝试将位置更新与mousemove事件分开的原因。奇怪的是,两个问题的答案都将requestAnimationFrame语句放回到mousemove事件中,这似乎与所引用的html5岩石文章所推荐并称为反跳的内容完全相反。也就是说,除非我遗漏了这一点。
下面提供的代码足够好,但是我想知道它是否应该与浏览器自身的拖动事件一样灵敏。在从下面的luke-codewalker的注释中了解了片段之后,我添加了具有固定位置元素的片段-一个常规拖动,另一个带有requestAnimationFrame。我没有发现两者之间有任何区别,而且两者的响应速度都比拖动浏览器自己的窗口之一慢。
谢谢。
更新(六个月后)
我没有试图以任何方式批评这种反跳方法,并且想知道我是否不理解它,因为今天我在自定义滚动条中尝试了相同的方法。我首先设置好它,只有在滚动条上的mousemove事件上,才可以更改元素的滚动位置。效果很好,但有点怪癖,与浏览器滚动条一样。我认为这可能是反跳方法的更好应用,因为页面中包含很多元素。因此,我将鼠标移动与屏幕更新分开,并使用requestAnimationFrame根据鼠标位置更新滚动位置,直到用户放开鼠标按钮为止。它也运行得很好,很难区别。我以为第一种方法看起来要好一些,让其他人看时不告诉她原因或区别,于是她也选择了第一种。
也许,在使用此方法的这两个应用程序中,我期望很高。或者,我仍然不了解某些内容,可以使动作更流畅。
"use strict";
document.querySelectorAll(".drag_handle")[0].addEventListener( 'mousedown', function(event) { drag_fixed( this.parentNode, event ); }, true );
document.querySelectorAll(".drag_handle_rAF")[0].addEventListener( 'mousedown', function(event) { drag_fixed_rAF( this.parentNode, event ); }, true );
function drag_fixed( e, evt )
{
evt.stopPropagation();
evt.preventDefault();
let dx = e.offsetLeft - evt.clientX,
dy = e.offsetTop - evt.clientY;
document.addEventListener( 'mousemove', move, true )
document.addEventListener( 'mouseup', stop, true );
function move(evt)
{
evt.stopPropagation();
e.style.left = ( evt.clientX + dx ) + 'px';
e.style.top = ( evt.clientY + dy ) + 'px';
} // close move
function stop(evt)
{
evt.stopPropagation();
document.removeEventListener( 'mousemove', move, true )
document.removeEventListener( 'mouseup', stop, true );
e = evt = dx = dy = null;
} // close stop
} // close drag_fixed
function drag_fixed_rAF( e, evt )
{
evt.stopPropagation();
evt.preventDefault();
let dx = e.offsetLeft - evt.clientX,
dy = e.offsetTop - evt.clientY,
x = evt.clientX,
y = evt.clientY,
r;
document.addEventListener( 'mousemove', move, true )
document.addEventListener( 'mouseup', stop, true );
requestAnimationFrame( update );
function move(evt)
{
evt.stopPropagation();
x = evt.clientX,
y = evt.clientY;
} // close move
function update()
{
e.style.left = ( x + dx ) + 'px';
e.style.top = ( y + dy ) + 'px';
r = requestAnimationFrame( update );
} // close update
function stop(evt)
{
evt.stopPropagation();
cancelAnimationFrame( r );
document.removeEventListener( 'mousemove', move, true )
document.removeEventListener( 'mouseup', stop, true );
e = evt = dx = dy = null;
} // close stop
} // close drag_fixed_rAF
* { box-sizing: border-box; }
html { background-color: rgba(73,110,147,0.75); }
body { margin: 0; }
.container {
position: fixed;
top: 50px;
left: 50px;
width: 300px;
height: 200px;
overflow-y: hidden;
background-color: white;
border-radius: 5px;
border: 1px solid black; }
.drag_handle, .drag_handle_rAF {
width: 100%;
height: 100%;
color: white;
background-color: rgb(90,120,70);
}
.scrollWindow {
overflow-y: auto;
position: absolute;
top: 75px;
left: 10px;
width: 280px;
height: 115px;
border-radius: 5px;
border: 1px solid black;
background-color: rgba(255,255,225,1);
}
.flexContainer {
position: absolute;
top: 35px;
left: 10px;
}
.data {
width: 100%;
padding: 30px 0 50px 0; }
.close { position : absolute; top: 5px; right: 5px; }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Drag Test</title>
<style>
</style>
</head>
<body>
<div class="container">
<div class="drag_handle">Drag Handle</div>
<button class="close">X</button>
<div class="flexContainer">
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
</div>
<div class= "scrollWindow">
<div class="data""></div>
</div>
</div>
<div class="container" style="left: 400px;">
<div class="drag_handle_rAF">Drag Handle rAF</div>
<button class="close">X</button>
<div class="flexContainer">
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
</div>
<div class= "scrollWindow">
<div class="data""></div>
</div>
</body
</html>