web-dev-qa-db-ja.com

JavaScriptを使用して、ドラッグアンドドロップdivを最初から実装する方法は?

CSSとJavaScriptの組み合わせである必要があります。実行する手順は次のとおりです。

  1. 他のすべての要素の上に配置します(指定するプロパティは?)
  2. クリックされたときにイベントをキャッチします(どのイベントをリッスンしますか?)
  3. マウスの移動に合わせてdivを移動します。

しかし、詳細は何ですか?

21
omg

JQueryの方法:

jQueryUI アドオン draggable および droppable を確認してください。

このような複雑なタスクを簡単にするために、文字通り数百時間がjQueryフレームワークに費やされています。 jQueryチームの取り組みを利用して、私たち全員がリッチなクロスブラウザーアプリケーションを簡単にプログラミングできるようにしてください;)

チャック・ノリスの方法:

あなたが生のjavascriptでこれを試すことを主張した場合。あなたはいくつかのことをしたいと思うでしょう。 1つは、プログラムですべてのドラッグ可能な項目を相対/絶対位置に設定することです。特定のアイテムをクリックした場合、CSSの上部/左側の値に、クリックが解放されるまでマウスのX、Y軸によって加えられた変更を反映させます。さらに、クリックしてドラッグ可能にしたときに、各ドラッグ可能オブジェクトのz-indexを更新する必要があります。

チュートリアル: JavaScriptでドラッグアンドドロップする方法

28
Sampson
  1. 高いZインデックスで絶対配置します。
  2. divのonmousedownを確認します。
  3. イベントのmouseXおよびmouseY属性を使用して、divを移動します。

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';
 }
14
Zack Marrapese

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>
5
maechler

標準のドラッグアンドドロップAPIは、広く認められています 大きな毛むくじゃらのロバボール 。そのため、最初から実行することはお勧めしません。しかし、それがあなたの質問なので、何かをドラッグ可能にするための要件のセットと、ドロップゾーンを正しく設定するための要件のセットがあります。

ドラッグ:

  • Domノードでは、「ドラッグ可能」プロパティをtrueに設定する必要があります

注意: e.dataTransfer.setDragImageを使用して、代替ドラッグイメージを設定できます(デフォルトは、ドラッグされているdomノードの透明イメージです。

注2:e.dataTransfer.setDatadragstartイベント内で使用して、ドロップイベントから取得できるデータを設定できます。

ドロップ:

  • 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マウスが動いていない場合でも起動します
  • dragleaveおよびdragenterは、マウスがリスニングdomノードに出入りしていない場合でも起動します(なんらかの愚かな理由で子の親のボナリーを横切ると起動します)
  • もっと..

より良い方法

私は、ドラッグアンドドロップライブラリを作成しました。これにより、標準のドラッグアンドドロップAPIを簡単に使用できるようになりました。ここでそれをチェックしてください:

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

3
B T

ええ、必要以上の機能を備えた肥大したライブラリが必要な場合は、jQueryを使用できます。または、エリート派になりたい場合は、サイズの1/10の Waltern Zornのドラッグアンドドロップライブラリ を使用します。

2
Josh Stodola
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
Waruna Manjula
  1. 他の要素の上にdivを表示するには、高いz-indexを割り当てる必要があります。さらに、ボックスシャドウを設定して、要素がドラッグ可能であることをユーザーにフィードバックすることができます。
  2. 合計3つのイベントをリッスンする必要があります:mousedownmouseup 、およびmousemovemousedownにリスナーを接続する必要がありますmousemove、これはマウスポインタの動きを追跡し、それに応じてdivを移動しますmouseupでリスナーを削除する必要がありますmousemove
  3. マウスでdivを移動するのは少し難しいです。 translate divをポインタの位置にすると、クリックしたときでも、ポインタは常に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>
1
Shahrukh Haider