web-dev-qa-db-ja.com

画面上の任意の場所にHTML5ドラッグアンドドロップ

作業中のプロジェクトのJavaScriptで記述したデバッガーログがあります。ログは基本的に、必要な場合にのみ表示されるHTML5の<aside>タグです。ログが特定のものに重なる可能性があるため、画面上でログを移動できるというアイデアをいじりたいと思っていました(これは私のプロジェクトにとっては問題ありません)。ただし、HTML5を使用してタグを適切にドラッグアンドドロップして、画面上の任意の場所(まあ、または<div>要素内)に配置できるようにする方法はわかりません。

HTML5のドラッグアンドドロップのサポートを読んだ後、それがどのように機能するかについての基本的な理解はありますが、divをどこにでも配置できるようになると、どこから始めるべきかわかりません(z-indexは高い値なので、私が言ったように、重複は結構です)。

助言がありますか?

ああ、このプロジェクトでは可能な限り外部ライブラリを使用しないようにしたいと思います。これを純粋なJavaScript/HTML5で実行しようとしています。

38
clicheName

ドラッグアンドドロップでは要素を移動しません。ドロップするときに要素を移動したい場合は、ドロップイベントで要素の新しい位置を設定する必要があります。 例は終了 これはFirefoxとChromeで動作します。ここにキーポイントがあります:

function drag_start(event) {
    var style = window.getComputedStyle(event.target, null);
    event.dataTransfer.setData("text/plain",
    (parseInt(style.getPropertyValue("left"),10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"),10) - event.clientY));
} 

dragstartイベントは、要素の左と上からのマウスポインターのオフセットを計算し、dataTransferに渡します。ページにドラッグ可能な要素が1つしかないため、IDを渡すことを心配していません。リンクや画像はありません。ページにそのような要素がある場合は、ここでもう少し作業を行う必要があります。

function drop(event) {
    var offset = event.dataTransfer.getData("text/plain").split(',');
    var dm = document.getElementById('dragme');
    dm.style.left = (event.clientX + parseInt(offset[0],10)) + 'px';
    dm.style.top = (event.clientY + parseInt(offset[1],10)) + 'px';
    event.preventDefault();
    return false;
}

dropイベントはオフセットをアンパックし、それらを使用して要素をマウスポインターに対して相対的に配置します。

dragoverイベントは、何かがドラッグされたときにpreventDefaultする必要があります。繰り返しますが、ページ上にドラッグ可能なものが他にある場合は、ここでもっと複雑なことをする必要があるかもしれません。

function drag_over(event) {
    event.preventDefault();
    return false;
} 

dropイベントとともにdocument.bodyにバインドして、すべてをキャプチャします。

var dm = document.getElementById('dragme');
dm.addEventListener('dragstart',drag_start,false);
document.body.addEventListener('dragover',drag_over,false);
document.body.addEventListener('drop',drop,false); 

これをIEで動作させたい場合は、asidea要素に変換する必要があります。もちろん、すべてのイベントバインディングコードドラッグアンドドロップAPIは、Operaや私が知っているモバイルブラウザでは動作しません。また、jQueryを使用したくないが、クロスブラウザイベントバインディングと要素の位置を操作することは、jQueryがはるかに簡単にすることです。

104
robertc

複数のアイテムの場合に、少しrobertcの素晴らしい答えを調整しました。ここで、secondclassの名前は、別の位置のためのものです。

<aside draggable="true" class="dragme" data-item="0">One</aside>
<aside draggable="true" class="dragme second" data-item="1">Two</aside>

Data-item属性をsetDatafunctionに追加します。

function drag_start(event) {
  var style = window.getComputedStyle(event.target, null);
  event.dataTransfer.setData("text/plain", (parseInt(style.getPropertyValue("left"), 10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"), 10) - event.clientY) + ',' + event.target.getAttribute('data-item'));
}

ドラッグされる要素をターゲットにします。

function drop(event) {
  var offset = event.dataTransfer.getData("text/plain").split(',');
  var dm = document.getElementsByClassName('dragme');
  dm[parseInt(offset[2])].style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
  dm[parseInt(offset[2])].style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
  event.preventDefault();
  return false;
}

クラスdragmeを持つすべての要素をループします。

var dm = document.getElementsByClassName('dragme');
for (var i = 0; i < dm.length; i++) {
  dm[i].addEventListener('dragstart', drag_start, false);
  document.body.addEventListener('dragover', drag_over, false);
  document.body.addEventListener('drop', drop, false);
}

ペン

6
Ingvi

ご回答有難うございます。 ChromeおよびFirefoxでうまく動作します。IEで動作するように調整しました。以下のコードです。

 <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)">
        <meta name="dcterms.created" content="Fri, 27 Jun 2014 21:02:23 GMT">
        <meta name="description" content="">
        <meta name="keywords" content="">
        <title></title>
        
        <!--[if IE]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
        <style>
        li
        { 
          position:  absolute;
          left: 0;
          top: 0; /* set these so Chrome doesn't return 'auto' from getComputedStyle */
          width: 200px; 
          background: rgba(255,255,255,0.66); 
          border: 2px  solid rgba(0,0,0,0.5); 
          border-radius: 4px; padding: 8px;
        }
        </style>
        <script>
            function drag_start(event) {
                var style = window.getComputedStyle(event.target, null);
                var str = (parseInt(style.getPropertyValue("left")) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top")) - event.clientY) + ',' + event.target.id;
                event.dataTransfer.setData("Text", str);
            }

            function drop(event) {
                var offset = event.dataTransfer.getData("Text").split(',');
                var dm = document.getElementById(offset[2]);
                dm.style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
                dm.style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
                event.preventDefault();
                return false;
            }

            function drag_over(event) {
                event.preventDefault();
                return false;
            }
        </script>
      </head>
      <body ondragover="drag_over(event)" ondrop="drop(event)">
       <ul>
              <li id="txt1" draggable="true" ondragstart="drag_start(event)"> Drag this text </li><br>
              <li id="txt2" draggable="true" ondragstart="drag_start(event)"> Drag me</li>
      </ul>
           <p>I never am really satisfied that I understand anything; because, understand it well as I may, my comprehension can only be an infinitesimal fraction of all I want to understand about the many connections and relations which occur to me, how the matter in question was first thought of or arrived at, etc., etc.</p>
           <p>In almost every computation a great variety of arrangements for the succession of the processes is possible, and various considerations must influence the selections amongst them for the purposes of a calculating engine. One essential object is to choose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation.</p>
           <p>Many persons who are not conversant with mathematical studies imagine that because the business of [Babbage’s Analytical Engine] is to give its results in numerical notation, the nature of its processes must consequently be arithmetical and numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine its numerical quantities exactly as if they were letters or any other general symbols; and in fact it might bring out its results in algebraical notation, were provisions made accordingly.</p>
           <p>The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform. It can follow analysis, but it has no power of anticipating any analytical revelations or truths. Its province is to assist us in making available what we are already acquainted with.</p>
    
      </body>
   </html>
5
Lavanya Karanam