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

问题描述 投票:0回答:9

应该是CSS和JavaScript的结合体。要做的步骤应该是:

  1. 使其位于所有其他元素之上(指定哪个属性?)
  2. 捕获点击时的事件(监听哪个事件?)
  3. 当鼠标移动时移动 div。

但是细节是什么?

javascript html css drag-and-drop
9个回答
38
投票

jQuery 方式:

查看 jQueryUI 插件 draggabledroppable

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

查克·诺里斯的方式:

如果您坚持使用原始 javascript 尝试此操作。你会想做一些事情。一,以编程方式将所有可拖动项目设置为相对/绝对定位。如果您单击某个特定项目,则使其 CSS 中的上/左值反映鼠标 x、y 轴所做的更改,直到释放单击为止。此外,当单击每个可拖动对象使其进入视图时,您需要更新其 z 索引。

教程:如何使用 Javascript 进行拖放


16
投票
  1. 使其绝对定位,并具有高 z-index。
  2. 检查 div 的 onmousedown。
  3. 使用事件的 mouseX 和 mouseY 属性来移动 div。

这是来自 Javascript,权威指南 的示例(已更新此处):

/**
 *  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';
 }

6
投票

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>

6
投票

标准的拖放 API 被广泛认为是“吸大毛驴球”。所以我不建议从头开始。但既然这是你的问题,那么有一组使某些东西可拖动的要求,以及一组正确设置拖放区域的要求: 拖动:

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 时存在很多问题,包括:

需要花费大量工作来区分放置区上的
    dragmove
  • 事件和与可拖动项目相关的
    dragmove
    事件
    即使鼠标没有移动,
  • dragmove
  • 也会触发
    即使你的鼠标没有移入或移出侦听 dom 节点,
  • dragleave
  • dragenter
    也会触发(只要它出于某种愚蠢的原因穿过子父边界,它就会触发)
    还有更多..
  • 更好的方法

我编写了一个拖放库,使使用标准拖放 API 变得更加容易,而无需遇到所有这些问题。在这里查看:

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


4
投票

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)); }
.mydiv {
    float: left;
    width: 100px;
    height: 35px;
    margin: 10px;
    padding: 10px;
    border: 1px solid black;
}
<!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>


2
投票
Waltern Zorn 的拖放库

,其大小只有十分之一。


1
投票
要将 div 置于其他元素之上,您必须为其指定一个高 z-index。此外,您可以设置 box-shadow 来向用户反馈该元素是可拖动的。
  1. 您总共必须监听三个事件:
  2. mousedownmouseupmousemove。在 mousedown 上,您必须在 mousemove 上附加一个侦听器,该侦听器跟踪鼠标指针移动并相应地移动 div,而在 mouseup 上,您必须删除 mousemove 上的侦听器. 用鼠标移动 div 有点棘手。如果您将 div
  3. 翻译到指针的位置,则指针将始终指向 div 的左上角,即使您单击右下角也是如此。为此,您必须在 mousedown 事件处理程序中计算 div(左上角)和鼠标指针之间的坐标差。然后,您必须在 mousemove 事件处理程序中将 div 转换到该位置之前减去鼠标位置的差值。 查看演示以获得更好的想法。

<!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>

w3schools 有一个很好的例子:
https://www.w3schools.com/howto/howto_js_draggable.asp

0
投票

HTML: <!-- Draggable DIV --> <div id="mydiv"> <!-- Include a header DIV with the same name as the draggable DIV, followed by "header" --> <div id="mydivheader">Click here to move</div> <p>Move</p> <p>this</p> <p>DIV</p> </div>

CSS:

#mydiv {
  position: absolute;
  z-index: 9;
  background-color: #f1f1f1;
  border: 1px solid #d3d3d3;
  text-align: center;
}

#mydivheader {
  padding: 10px;
  cursor: move;
  z-index: 10;
  background-color: #2196F3;
  color: #fff;
}

JS:

// Make the DIV element draggable:
dragElement(document.getElementById("mydiv"));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

您可以使用以下代码来完成此操作

-1
投票

$(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>


    

© www.soinside.com 2019 - 2024. All rights reserved.