在本机javascript中创建一个可拖动的div [重复]
Posted
技术标签:
【中文标题】在本机javascript中创建一个可拖动的div [重复]【英文标题】:Create a draggable div in native javascript [duplicate] 【发布时间】:2012-10-20 14:15:56 【问题描述】:我想在原生 javascript 中创建一个可移动/可拖动的 div,而不使用 jquery 和库。有教程之类的吗?
【问题讨论】:
看这里 [***.com/questions/9334084/… 为了让您了解它的工作原理:首先您需要将 onmousedown 和 onmouseup 事件处理程序附加到一个 div。然后您需要将 div 的 x 和 y 坐标更改为指针位置的坐标(但您必须考虑元素第一次拖动时的偏移量)。哦,别忘了将元素的位置设置为“绝对” 【参考方案1】:好的,这是我用于轻量级部署的个人代码(不允许使用库或出于某种原因过度使用库的项目)。首先,我总是使用这个方便的函数,这样我就可以传递一个 id 或实际的 dom 元素:
function get (el)
if (typeof el == 'string') return document.getElementById(el);
return el;
作为奖励,get()
的输入时间比 document.getElementById()
短,我的代码最终也更短。
第二次意识到大多数库正在做的是跨浏览器兼容性。如果所有浏览器的行为都相同,则代码相当简单。所以让我们编写一些跨浏览器函数来获取鼠标位置:
function mouseX (e)
if (e.pageX)
return e.pageX;
if (e.clientX)
return e.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
return null;
function mouseY (e)
if (e.pageY)
return e.pageY;
if (e.clientY)
return e.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
return null;
好的,上面的两个功能是一样的。当然有更好的方法来编写它们,但我现在(相对)保持简单。
现在我们可以编写拖放代码了。我喜欢这段代码的一点是,所有内容都在一个闭包中捕获,因此没有全局变量或辅助函数在浏览器中乱扔垃圾。此外,代码将拖动手柄与被拖动的对象分开。这对于创建对话框等很有用。但如果不需要,您始终可以为它们分配相同的对象。无论如何,这是代码:
function dragable (clickEl,dragEl)
var p = get(clickEl);
var t = get(dragEl);
var drag = false;
offsetX = 0;
offsetY = 0;
var mousemoveTemp = null;
if (t)
var move = function (x,y)
t.style.left = (parseInt(t.style.left)+x) + "px";
t.style.top = (parseInt(t.style.top) +y) + "px";
var mouseMoveHandler = function (e)
e = e || window.event;
if(!drag)return true;
var x = mouseX(e);
var y = mouseY(e);
if (x != offsetX || y != offsetY)
move(x-offsetX,y-offsetY);
offsetX = x;
offsetY = y;
return false;
var start_drag = function (e)
e = e || window.event;
offsetX=mouseX(e);
offsetY=mouseY(e);
drag=true; // basically we're using this to detect dragging
// save any previous mousemove event handler:
if (document.body.onmousemove)
mousemoveTemp = document.body.onmousemove;
document.body.onmousemove = mouseMoveHandler;
return false;
var stop_drag = function ()
drag=false;
// restore previous mousemove event handler if necessary:
if (mousemoveTemp)
document.body.onmousemove = mousemoveTemp;
mousemoveTemp = null;
return false;
p.onmousedown = start_drag;
p.onmouseup = stop_drag;
offsetX/offsetY
计算稍微复杂是有原因的。如果您注意到,它只是获取鼠标位置之间的差异并将它们添加回被拖动的 div 的位置。为什么不只使用鼠标位置?好吧,如果你这样做,当你点击它时,div 会跳转到鼠标指针。这是我不想要的行为。
【讨论】:
上面的代码是演示。复制粘贴到 html 文件中(包括辅助函数)并在页面中的 div 上调用该函数。 注意:我也会把 p.onmouseout = stop_drag;鼠标事件接近尾声。当我运行代码时,有时我的鼠标会比元素移动得更快,当鼠标离开元素时,你必须先单击并释放它,然后它才会停止动作。 要运行它,只需将其放入脚本中:window.onload=function()dragable('testdiv','testdiv');; 而这在你的 HTML 中: H train【参考方案2】:你可以试试这个
HTML
<div id="one" style="height:50px; width:50px; border:1px solid #ccc; background:red;">
</div>
可拖动 div 的 Js 脚本
window.onload = function()
draggable('one');
;
var dragObj = null;
function draggable(id)
var obj = document.getElementById(id);
obj.style.position = "absolute";
obj.onmousedown = function()
dragObj = obj;
document.onmouseup = function(e)
dragObj = null;
;
document.onmousemove = function(e)
var x = e.pageX;
var y = e.pageY;
if(dragObj == null)
return;
dragObj.style.left = x +"px";
dragObj.style.top= y +"px";
;
检查这个Demo
【讨论】:
如何防止鼠标移动到左上角。我想将鼠标放在相对于它在 div 中单击的位置的位置 这很棒而且很简单,我只是添加了一个小改动。为了防止从 dom 中删除 obj 时发生泄漏,obj.onmousedown 处理程序不应引用 obj,而应引用 e.currentTarget。 最佳解决方案。谢谢。 这适用于简单的情况,但一旦你有嵌套元素,它就不起作用了。如果您在可拖动之后有任何项目,您的布局将由于位置的硬设置而中断:绝对。【参考方案3】:这段代码修正了鼠标的位置(所以当你开始拖动时,被拖动的对象不会跳跃)并且也适用于触摸屏/手机
var dragObj = null; //object to be moved
var xOffset = 0; //used to prevent dragged object jumping to mouse location
var yOffset = 0;
window.onload = function()
document.getElementById("menuBar").addEventListener("mousedown", startDrag, true);
document.getElementById("menuBar").addEventListener("touchstart", startDrag, true);
document.onmouseup = stopDrag;
document.ontouchend = stopDrag;
function startDrag(e)
/*sets offset parameters and starts listening for mouse-move*/
e.preventDefault();
e.stopPropagation();
dragObj = e.target;
dragObj.style.position = "absolute";
var rect = dragObj.getBoundingClientRect();
if(e.type=="mousedown")
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
else if(e.type=="touchstart")
xOffset = e.targetTouches[0].clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
function dragObject(e)
/*Drag object*/
e.preventDefault();
e.stopPropagation();
if(dragObj == null) return; // if there is no object being dragged then do nothing
else if(e.type=="mousemove")
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
else if(e.type=="touchmove")
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
function stopDrag(e)
/*End dragging*/
if(dragObj)
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
divheight:400px; width:400px; border:1px solid #ccc; background:blue; cursor: pointer;
<div id="menuBar" >A</div>
【讨论】:
我更新了您的代码以订阅 touchend 事件。否则拖动不会在触摸设备上停止。【参考方案4】:<div draggable=true ondragstart="event.dataTransfer.setData('text/plain', '12345')">
drag me
</div>
<div ondragover="return false;" ondrop="this.innerHTML=event.dataTransfer.getData('text/plain')">
drop on me
</div>
【讨论】:
很酷,但可能不是 OP 所说的“可拖动 div”...以上是关于在本机javascript中创建一个可拖动的div [重复]的主要内容,如果未能解决你的问题,请参考以下文章