在本机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;
&lt;div id="menuBar" &gt;A&lt;/div&gt;

【讨论】:

我更新了您的代码以订阅 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 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

我想在闪亮中创建一个可拖动的 modalDialog

在 React Native 中创建一个可拖动、可调整大小的框

可拖动 div 的 z-index 顺序

如何在 HTML5 Canvas 中创建可拖动的线条?

如何在 WordPress 中创建自定义可拖动小部件

如何在 Java 中创建可拖动对象?