可移动/可拖动 <div>

IT技术 javascript draggable move mousemove
2021-02-26 04:53:41

这是我更新和修改的脚本,它完全有效,除了我想通用化它...观察****我如何制作它,这样我就不必function(e){BOX.Draggable.elemen = e.target || e.srcElement; elementDraggable(e);每次需要使用可拖动功能时都这样做对于不同的元素?

window.onload = addListeners;

var BOX = function(){
  return{
    Draggable: function(){}
  };
}();

function addListeners(){
  document.getElementById('div').addEventListener('contextmenu', menumove, false);
  **document.getElementById('div').addEventListener('mousedown', function(e){BOX.Draggable.elemen = e.target || e.srcElement; elementDraggable(e);}, false);**
}

function elementDraggable(e){
  var e = e || window.event;
  var div = BOX.Draggable.elemen;
  BOX.Draggable.innerX = e.clientX + window.pageXOffset - div.offsetLeft;
  BOX.Draggable.innerY = e.clientY + window.pageYOffset - div.offsetTop;

  window.addEventListener('mousemove', elementMove, false);
  window.addEventListener('mouseup', function(){
    window.removeEventListener('mousemove', elementMove, false);
    }, true);

  function elementMove(e){
    div.style.position = 'absolute';
    div.style.left = e.clientX + window.pageXOffset - BOX.Draggable.innerX + 'px';
    div.style.top = e.clientY + window.pageYOffset - BOX.Draggable.innerY + 'px';
  }
}
6个回答

jQuery 是您的选择吗?由于代码已经存在,它使您正在做的事情变得非常简单。

http://jqueryui.com/demos/draggable/

演示

JavaScript 代码

window.onload = addListeners;

function addListeners(){
    document.getElementById('dxy').addEventListener('mousedown', mouseDown, false);
    window.addEventListener('mouseup', mouseUp, false);

}

function mouseUp()
{
    window.removeEventListener('mousemove', divMove, true);
}

function mouseDown(e){
  window.addEventListener('mousemove', divMove, true);
}

function divMove(e){
    var div = document.getElementById('dxy');
  div.style.position = 'absolute';
  div.style.top = e.clientY + 'px';
  div.style.left = e.clientX + 'px';
}​
是的,它没有保存最新的我刚刚意识到它。我在重写
2021-04-21 04:53:41
有没有任何理由的功能mouseDownmouseUpuseCapture参数集true附加事件的时候?虽然addListeners功能使用false 附加事件的时候?
2021-04-23 04:53:41
我已经知道如何用 jquery 做到这一点,我正在尝试学习如何用 javascript 手动做到这一点,谢谢。
2021-04-25 04:53:41
@AndersonGreen 您必须考虑拖动开始的位置。如果您从 div 的中间开始拖动,则必须通过该位置偏移位置。请参阅jsfiddle.net/wfbY8/737(我知道旧评论,但需要回复..)
2021-05-03 04:53:41
MrRioku 确实如此,但如果他已经在加载库,那将是他的最佳选择。他不是,所以我向他提供了直接的 JavaScript 代码。
2021-05-13 04:53:41

这是一个很好的无 jQuery 脚本来拖动 div:http : //jsfiddle.net/g6m5t8co/1/

<!doctype html>
<html>
    <head>
        <style>
            #container {
                position:absolute;
                background-color: blue;
                }
            #elem{
                position: absolute;
                background-color: green;
                -webkit-user-select: none;
                -moz-user-select: none;
                -o-user-select: none;
                -ms-user-select: none;
                -khtml-user-select: none;     
                user-select: none;
            }
        </style>
        <script>
            var mydragg = function(){
                return {
                    move : function(divid,xpos,ypos){
                        divid.style.left = xpos + 'px';
                        divid.style.top = ypos + 'px';
                    },
                    startMoving : function(divid,container,evt){
                        evt = evt || window.event;
                        var posX = evt.clientX,
                            posY = evt.clientY,
                        divTop = divid.style.top,
                        divLeft = divid.style.left,
                        eWi = parseInt(divid.style.width),
                        eHe = parseInt(divid.style.height),
                        cWi = parseInt(document.getElementById(container).style.width),
                        cHe = parseInt(document.getElementById(container).style.height);
                        document.getElementById(container).style.cursor='move';
                        divTop = divTop.replace('px','');
                        divLeft = divLeft.replace('px','');
                        var diffX = posX - divLeft,
                            diffY = posY - divTop;
                        document.onmousemove = function(evt){
                            evt = evt || window.event;
                            var posX = evt.clientX,
                                posY = evt.clientY,
                                aX = posX - diffX,
                                aY = posY - diffY;
                                if (aX < 0) aX = 0;
                                if (aY < 0) aY = 0;
                                if (aX + eWi > cWi) aX = cWi - eWi;
                                if (aY + eHe > cHe) aY = cHe -eHe;
                            mydragg.move(divid,aX,aY);
                        }
                    },
                    stopMoving : function(container){
                        var a = document.createElement('script');
                        document.getElementById(container).style.cursor='default';
                        document.onmousemove = function(){}
                    },
                }
            }();

        </script>
    </head>
    <body>
        <div id='container' style="width: 600px;height: 400px;top:50px;left:50px;">     
            <div id="elem" onmousedown='mydragg.startMoving(this,"container",event);' onmouseup='mydragg.stopMoving("container");' style="width: 200px;height: 100px;">
                <div style='width:100%;height:100%;padding:10px'>
                <select id=test>
                    <option value=1>first
                    <option value=2>second
                </select>
                <INPUT TYPE=text value="123">
                </div>
            </div>
        </div>  
    </body>
</html>
Davvit,为容器添加“onmouseout”。
2021-04-26 04:53:41
是的很好的例子!它的另一个问题是,如果您开始在绿框外拖动和移动光标,则鼠标向上不会注册......换句话说,鼠标向上事件不会在绿框外注册。
2021-04-27 04:53:41
2021-04-27 04:53:41
函数中的var a = document.createElement('script');那一行有什么用stopMoving
2021-05-03 04:53:41
很棒的解决方案!它非常通用,还确保您不能将 div 移动到父容器之外!
2021-05-13 04:53:41

好吧,您的移动代码简化为:

div.style.position = "absolute";
div.style.top = e.clientY - (e.clientY - div.offsetTop) + "px";
div.style.left = e.clientX - (e.clientX - div.offsetLeft) + "px";

这里的基本数学 - the e.clientXande.clientY对这里的位置绝对没有影响,所以你只是把offsetLeft它重新分配给style.left,对于顶部也是如此。因此没有任何运动。

你需要做的是保存clientXclientYmousedown发生,并以此为基础进行减法。

哦,您还设置了错误的事件侦听器。现在的方式是,它运行divMove一次,返回值(undefined此处)是作为侦听器附加的函数。相反,使用function(e) {divMove(dxy,e || window.event);}.

谢谢你让我自己做。我能够弄清楚几乎所有事情,只是需要一点帮助,因为我不知道该removeEventListener方法:-)
2021-04-18 04:53:41
是的 ^_^ 我自己的拖放代码只是使用elem.onmousemove,将其设置为null而不是removeEventListener个人喜好。
2021-04-22 04:53:41
你在对另一个答案的评论中说你正在努力学习,所以我不会为你做这件事,但基本上你有两种主要的方法来做到这一点。1) 使用绝对定位,获取当前鼠标坐标并将元素设置为这些坐标。2) 使用相对定位,取当前位置与起始位置的差值。
2021-05-10 04:53:41
我基本上明白你在说什么,我可以看出你是对的。但我不确定如何将其更改为您所说的。你能放一个片段来告诉我你的意思吗?
2021-05-12 04:53:41

稍微修改了Shaedo 的代码,将它包装在一个函数中,并添加了一个功能,您可以仅通过元素的一部分或其子元素来拖动元素,例如 div 的标题栏。请注意,在本演示中,您只能拖动红色区域来移动蓝色区域。

function makeDragable(dragHandle, dragTarget) {
  let dragObj = null; //object to be moved
  let xOffset = 0; //used to prevent dragged object jumping to mouse location
  let yOffset = 0;

  document.querySelector(dragHandle).addEventListener("mousedown", startDrag, true);
  document.querySelector(dragHandle).addEventListener("touchstart", startDrag, true);

  /*sets offset parameters and starts listening for mouse-move*/
  function startDrag(e) {
    e.preventDefault();
    e.stopPropagation();
    dragObj = document.querySelector(dragTarget);
    dragObj.style.position = "absolute";
    let 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;
      yOffset = e.targetTouches[0].clientY - rect.top;
      window.addEventListener('touchmove', dragObject, true);
    }
  }

  /*Drag object*/
  function dragObject(e) {
    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";
    }
  }

  /*End dragging*/
  document.onmouseup = function(e) {
    if (dragObj) {
      dragObj = null;
      window.removeEventListener('mousemove', dragObject, true);
      window.removeEventListener('touchmove', dragObject, true);
    }
  }
}

makeDragable('#handle', '#moveable')
#moveable {
    width: 100px;
    height: 100px;
    background: blue;
}

#handle {
    width: 50px;
    height: 50px;
    cursor: move;
    background: red;
}
<div id="moveable">
    <div id="handle">
    </div>
</div>

这绝对应该是公认的答案:它的方法通用,易于使用,甚至支持触摸事件。哦,它考虑到通常要拖动的容器与您拖动它的手柄不同。非常感谢!!:)
2021-05-07 04:53:41

在尝试了 jnoreiga 接受的答案后,我发现被拖动的元素突然吸附到左上角而不是保持相同的相对位置非常烦人。

该代码段通过偏移防止了上述尴尬的行为,并提供了一个简单的界面来一次创建一个或通过forEach调用或类似方式批量创建可拖动元素

window.onload = function() {
  draggable(document.getElementById('foo'));
}

function draggable(el) {
  el.addEventListener('mousedown', function(e) {
    var offsetX = e.clientX - parseInt(window.getComputedStyle(this).left);
    var offsetY = e.clientY - parseInt(window.getComputedStyle(this).top);
    
    function mouseMoveHandler(e) {
      el.style.top = (e.clientY - offsetY) + 'px';
      el.style.left = (e.clientX - offsetX) + 'px';
    }

    function reset() {
      window.removeEventListener('mousemove', mouseMoveHandler);
      window.removeEventListener('mouseup', reset);
    }

    window.addEventListener('mousemove', mouseMoveHandler);
    window.addEventListener('mouseup', reset);
  });
}
/* The only required styling is position: absolute */
#foo {
  position: absolute;
  border: 1px solid black;
  overflow: hidden;
}

/* Prevents inconsistent highlighting of element while being dragged
   Copied from https://stackoverflow.com/questions/826782 */
.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */
}
<div id="foo" class="noselect">This is a draggable div!</div>