如何使用JavaScript从头开始实现拖放div?

时间:2009-06-24 18:10:45

标签: javascript html css drag-and-drop

它应该是CSS和JavaScript的组合。要做的步骤应该是:

  1. 将其置于所有其他元素之上(指定哪个属性?)
  2. 点击事件时收听事件(要收听哪个事件?)
  3. 当鼠标移动时移动div。
  4. 但有什么细节?

8 个答案:

答案 0 :(得分:28)

jQuery方式:

查看jQueryUI插件draggabledroppable

在jQuery框架中投入了数百个小时来完成这样复杂的任务,这几乎是微不足道的。利用jQuery团队的努力,使我们所有人都可以更轻松地编写丰富的跨浏览器应用程序;)

查克诺里斯的方式:

如果您坚持使用原始javascript尝试此操作。你会想要做一些事情。一,以编程方式将所有可拖动项目设置为相对/绝对定位。如果单击特定项目,则使其在CSS中的顶部/左侧值反映鼠标的x,y轴所做的更改,直到释放单击。此外,您还需要在点击每个可拖动的z-index时更新它的z-index。

教程:How to Drag and Drop with Javascript

答案 1 :(得分:14)

  1. 使其具有绝对定位,具有高z-index。
  2. 检查div的onmousedown。
  3. 使用事件的mouseX和mouseY属性移动div。
  4. 以下是Javascript, the Definitive Guide(已更新here)的示例:

    /**
     *  Drag.js:    drag absolutely positioned HTML elements.
     *
     *  This module defines a single drag() function that is designed to be called
     *  from an onmousedown event handler. Subsequent mousemove event will
     *  move the specified element. A mouseup event will terminate the drag.
     *  If the element is dragged off the screen, the window does not scroll.
     *  This implementation works with both the DOM Level 2 event model and the
     *  IE event model.
     *
     *  Arguments:
     *
     *      elementToDrag: the element that received the mousedown event or
     *          some containing element. It must be absolutely positioned. Its
     *          style.left and style.top values will be changed based on the user's
     *          drag.
     *
     *      event: ethe Event object for the mousedown event.
     *
     *  Example of how this can be used:
     *      <script src="Drag.js"></script> <!-- Include the Drag.js script -->
     *      <!-- Define the element to be dragged -->
     *      <div style="postion:absolute; left:100px; top:100px; width:250px;
     *                  background-color: white; border: solid black;">
     *      <!-- Define the "handler" to drag it with. Note the onmousedown attribute. -->
     *      <div style="background-color: gray; border-bottom: dotted black;
     *                  padding: 3px; font-family: sans-serif; font-weight: bold;"
     *          onmousedown="drag(this.parentNode, event);">
     *      Drag Me <!-- The content of the "titlebar" -->
     *      </div>
     *      <!-- Content of the draggable element -->
     *      <p>This is a test. Testing, testing, testing.<p>This is a test.<p>Test.
     *      </div>
     *
     *  Author: David Flanagan; Javascript: The Definitive Guide (O'Reilly)
     *  Page: 422
     **/
     function drag(elementToDrag, event)
     {
         // The mouse position (in window coordinates)
         // at which the drag begins
         var startX = event.clientX, startY = event.clientY;
    
         // The original position (in document coordinates) of the
         // element that is going to be dragged. Since elementToDrag is
         // absolutely positioned, we assume that its offsetParent is the
         //document bodt.
         var origX = elementToDrag.offsetLeft , origY = elementToDrag.offsetTop;
    
         // Even though the coordinates are computed in different
         // coordinate systems, we can still compute the difference between them
         // and use it in the moveHandler() function. This works because
         // the scrollbar positoin never changes during the drag.
         var deltaX = startX - origX, deltaY = startY - origY;
    
         // Register the event handlers that will respond to the mousemove events
         // and the mouseup event that follow this mousedown event.
         if (document.addEventListener) //DOM Level 2 event model
         {
             // Register capturing event handlers
             document.addEventListener("mousemove", moveHandler, true);
             document.addEventListener("mouseup", upHandler, true);
         }
         else if (document.attachEvent) //IE 5+ Event Model
         {
             //In the IE event model, we capture events by calling
             //setCapture() on the element to capture them.
             elementToDrag.setCapture();
             elementToDrag.attachEvent("onmousemove", moveHandler);
             elementToDrag.attachEvent("onmouseup", upHandler);
             // Treat loss of mouse capture as a mouseup event.
             elementToDrag.attachEvent("onclosecapture", upHandler);
         }
         else //IE 4 Event Model
         {
             // In IE 4, we can't use attachEvent() or setCapture(), so we set
             // event handlers directly on the document object and hope that the
             // mouse event we need will bubble up.
             var oldmovehandler = document.onmousemove; //used by upHandler()
             var olduphandler = document.onmouseup;
             document.onmousemove = moveHandler;
             document.onmouseup = upHandler;
         }
    
         // We've handled this event. Don't let anybody else see it.
         if (event.stopPropagation) event.stopPropagation();    //  DOM Level 2
         else event.cancelBubble = true;                        //  IE
    
         // Now prevent any default action.
         if (event.preventDefault) event.preventDefault();      //  DOM Level 2
         else event.returnValue = false;                        //  IE
    
         /**
          * This is the handler that captures mousemove events when an element
          * is being dragged. It is responsible for moving the element.
          **/
          function moveHandler(e)
          {
              if (!e) e = window.event; //  IE Event Model
    
              // Move the element to the current mouse position, adjusted as
              // necessary by the offset of the initial mouse-click.
              elementToDrag.style.left = (e.clientX - deltaX) + "px";
              elementToDrag.style.top = (e.clientY - deltaY) + "px";
    
              // And don't let anyone else see this event.
              if (e.stopPropagation) e.stopPropagation();       // DOM Level 2
              else e.cancelBubble = true;                       // IE
          }
    
          /**
           * This is the handler that captures the final mouseup event that
           * occurs at the end of a drag.
           **/
           function upHandler(e)
           {
               if (!e) e = window.event;    //IE Event Model
    
               // Unregister the capturing event handlers.
               if (document.removeEventListener) // DOM event model
                {
                    document.removeEventListener("mouseup", upHandler, true);
                    document.removeEventListener("mousemove", moveHandler, true);
                }
                else if (document.detachEvent)  //  IE 5+ Event Model
                {
                    elementToDrag.detachEvent("onlosecapture", upHandler);
                    elementToDrag.detachEvent("onmouseup", upHandler);
                    elementToDrag.detachEvent("onmousemove", moveHandler);
                    elementToDrag.releaseCapture();
                }
                else    //IE 4 Event Model
                {
                    //Restore the original handlers, if any
                    document.onmouseup = olduphandler;
                    document.onmousemove = oldmovehandler;
                }
    
                //  And don't let the event propagate any further.
                if (e.stopPropagation) e.stopPropagation(); //DOM Level 2
                else e.cancelBubble = true;                 //IE
           }
     }
    
     function closeMe(elementToClose)
     {
         elementToClose.innerHTML = '';
         elementToClose.style.display = 'none';
     }
    
     function minimizeMe(elementToMin, maxElement)
     {
         elementToMin.style.display = 'none';
     }
    

答案 2 :(得分:4)

HTML5拖放

如果您在2017年或之后阅读此内容,您可能需要查看HTML5拖放API:

https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API

示例:

<!DOCTYPE HTML>
<html>
<head>
    <script>
    function allowDrop(ev) {
        ev.preventDefault();
    }

    function drag(ev) {
        ev.dataTransfer.setData("text", ev.target.id);
    }

    function drop(ev) {
        ev.preventDefault();
        var data = ev.dataTransfer.getData("text");
        ev.target.appendChild(document.getElementById(data));
    }
    </script>
    <style>
        .draggable {
            border: 1px solid black;
            width: 30px;
            height: 20px;
            float: left;
            margin-right: 5px;
        }
        #target {
            border: 1px solid black;
            width: 150px;
            height: 100px;
            padding: 5px;
        }
    </style>
</head>
<body>

    <h1>Drag and Drop</h1>

    <h2>Target</h2>
    <div id="target" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

    <h2>Draggable Elements</h2>
    <div id="draggable1" class="draggable" draggable="true" ondragstart="drag(event)"></div>
    <div id="draggable2" class="draggable" draggable="true" ondragstart="drag(event)"></div>
    <div id="draggable3" class="draggable" draggable="true" ondragstart="drag(event)"></div>

</body>
</html>

答案 3 :(得分:2)

是的,如果你想要一个功能远远超过你需要的膨胀库,你可以使用jQuery!或者如果你想成为精英阶层,请使用Waltern Zorn's drag and drop library,这是十分之一。

答案 4 :(得分:2)

&#13;
&#13;
function allowDrop(ev) {
    ev.preventDefault();
}

function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
}
&#13;
.mydiv {
    float: left;
    width: 100px;
    height: 35px;
    margin: 10px;
    padding: 10px;
    border: 1px solid black;
}
&#13;
<!DOCTYPE HTML>
<html>
<head>


</head>
<body>

<h2>Drag and Drop</h2>


<div id="div1" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>

<div id="div2" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div3" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div4" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

</body>
</html>
&#13;
&#13;
&#13;

答案 5 :(得分:1)

标准的拖放API被suck big hairy donkey balls广泛认可。所以我不建议从头开始。但是,既然这是你的问题,那么制作可拖动的东西有一套要求,以及正确设置放置区的一套要求:

Dragging功能:

  • dom节点必须将“draggable”属性设置为true

注意:e.dataTransfer.setDragImage可用于设置备用拖动图像(默认为拖动的dom节点的透明图像。

注意2:e.dataTransfer.setData可以在dragstart事件中使用,以设置一些可以从drop事件中获取的数据。

滴:

  • dragover事件中,必须调用e.preventDefault
  • drop事件中,必须调用e.preventDefault

示例:

<body>
    <div id="dragme" draggable="true">Drag Me</div>
    <div id="dropzone">Drop Here</div>
</body>

<script>
    var dragme = document.getElementById('dragme')
    var dropzone = document.getElementById('dropzone')

    dragme.addEventListener('dragstart',function(e){
        dropzone.innerHTML = "drop here"
    })

    dropzone.addEventListener('dragover',function(e){
        e.preventDefault()
    })
    dropzone.addEventListener('drop',function(e){
        e.preventDefault()
        dropzone.innerHTML = "dropped"
    })
</script>

但是,使用此API有很多问题,包括:

  • 要区分dropzone上的dragmove事件和与可拖动项目相关的dragmove事件需要做大量的工作
  • 即使你的鼠标没有移动,
  • dragmove也会发光
  • dragleavedragenter即使您的鼠标没有移入或移出侦听dom节点也会触发(因为某些愚蠢的原因,只要它跨越了一个子父节点就会触发)
  • 还有更多..

更好的方法

我写了一个拖放库,这使得使用标准的拖放API更容易,而没有所有这些问题。在这里查看:

https://github.com/fresheneesz/drip-drop

答案 6 :(得分:1)

  1. 要将div置于其他元素之上,您必须为其分配较高的z索引。另外,您可以设置box-shadow来向用户反馈该元素是可拖动的。
  2. 您必须共听三个事件: 鼠标按下 鼠标按下 mousemove 。在 鼠标 上,您必须在 mousemove 上附加一个侦听器,该监听器可跟踪鼠标指针的移动并相应地移动div ,并且在 鼠标 上,您必须在 mousemove 上删除监听器。
  3. 用鼠标移动div有点棘手。如果将div 翻译 到指针的位置,即使单击右下角,指针也将始终指向div的左上角。为此,您必须在 mousedown 事件处理程序中计算div(左上角)与鼠标指针之间的坐标差。然后,必须在 mousemove 事件处理程序中,将div转换为鼠标位置之前从鼠标位置中减去该差异。

See the demo for a better idea.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      body,
      html {
        width: 100%;
        height: 100%;
        padding: 0px;
        margin: 0px;
      }
      #box {
        width: 100px;
        height: 100px;
        margin: auto;
        background-color: lightblue;
      }
      #box:active {
        border: 1px solid black;
        box-shadow: 2px 2px 5px 5px #bbb6b6;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
  </body>
  <script>
    var box = document.getElementById("box");
    var diff = {};
    var getBoxPos = function() {
      return {
        x: box.getBoundingClientRect().x,
        y: box.getBoundingClientRect().y
      };
    };
    var calcDiff = function(x, y) {
      var boxPos = getBoxPos();
      diff = {
        x: x - boxPos.x,
        y: y - boxPos.y
      };
    };
    var handleMouseMove = function(event) {
      var x = event.x;
      var y = event.y;
      x -= diff.x;
      y -= diff.y;

      console.log("X " + x + " Y " + y);
      box.style.position = "absolute";
      box.style.transform = "translate(" + x + "px ," + y + "px)";
    };

    box.addEventListener("mousedown", function(e) {
      calcDiff(e.x, e.y);
      box.addEventListener("mousemove", handleMouseMove, true);
    });

    box.addEventListener("mouseup", function(e) {
      console.log("onmouseup");
      box.removeEventListener("mousemove", handleMouseMove, true);
    });
  </script>
</html>

答案 7 :(得分:0)

您可以通过使用以下代码来实现

$(function() { 
        $("#imageListId").sortable({ 
            update: function(event, ui) { 
                    getIdsOfImages(); 
                } //end update          
        }); 
    }); 
  
    function getIdsOfImages() { 
        var values = []; 
        $('.listitemClass').each(function(index) { 
            values.push($(this).attr("id") 
                        .replace("imageNo", "")); 
        }); 
        $('#outputvalues').val(values); 
    }
/* text align for the body */
    body { 
        text-align: center; 
    } 
      
    /* image dimension */
    img { 
        height: 200px; 
        width: 350px; 
    } 
      
    /* imagelistId styling */
    #imageListId { 
        margin: 0; 
        padding: 0; 
        list-style-type: none; 
    } 
       
    #imageListId div { 
        margin: 0 4px 4px 4px; 
        padding: 0.4em; 
        display: inline-block; 
    } 
      
    /* Output order styling */
    #outputvalues { 
        margin: 0 2px 2px 2px; 
        padding: 0.4em; 
        padding-left: 1.5em; 
        width: 250px; 
        border: 2px solid dark-green; 
        background: gray; 
    } 
       
    .listitemClass { 
        border: 1px solid #006400; 
        width: 350px; 
    } 
       
    .height { 
        height: 10px; 
    }
<link href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>

<!DOCTYPE html> 
<html> 
<head> 
    <title> 
        Drag Drop feature
    </title> 
</head> 
       
<body> 
    <h1 style="color:green">GeeksforGeeks</h1>  
      
    <b>Drag and drop using jQuery UI Sortable</b> 
      
    <div class="height"></div><br> 
      
    <div id = "imageListId"> 
        <div id="imageNo1" class = "listitemClass"> 
            <img src="images/geeksimage1.png" alt=""> 
        </div> 
          
        <div id="imageNo2" class = "listitemClass"> 
            <img src="images/geeksimage2.png" alt=""> 
        </div> 
          
        <div id="imageNo3" class = "listitemClass"> 
            <img src="images/geeksimage3.png" alt=""> 
        </div> 
          
        <div id="imageNo4" class = "listitemClass"> 
            <img src="images/geeksimage4.png" alt=""> 
        </div> 
          
        <div id="imageNo5" class = "listitemClass"> 
            <img src="images/geeksimage5.png" alt=""> 
        </div> 
          
        <div id="imageNo6" class = "listitemClass"> 
            <img src="images/geeksimage6.png" alt=""> 
        </div> 
    </div> 
      
    <div id="outputDiv"> 
        <b>Output of ID's of images : </b> 
        <input id="outputvalues" type="text" value="" /> 
    </div> 
</body> 
  
</html>