5

ネイティブのドラッグ アンド ドロップ イベントを使用して DOM SVG 要素を並べ替えようとしています。以下のコードは、Firefox では (いくつかの奇妙な画像効果で) 動作するようです。私の最善の推測は、問題のイベントについて、私が正しく考えていない何か、ある種のリセットがあるということです。または、この方法で dataTransfer を使用せずにドラッグ イベントを使用するのは正しくない可能性があります。私の目標は、ライブラリを使用せずにこのタイプの関数を理解することですが、最も基本的なレベルで DOM 関数、JavaScript、HTML、および CSS をより明確に理解することです。そのリストのどこでも簡単に間違っている可能性があります。

<!DOCTYPE html>
<html>
  <head>
    <title>Drag and Drop Experiments</title>
    <style>svg { border-width:3px} </style>
  </head>
<body>
  <div id="main">
    <svg id="s1" draggable="yes" width="100" height="100">
      <circle cx="50" cy="50" r="30" fill="blue"></circle>
    </svg>
    <svg id="s2" draggable="yes" width="100" height="100">
      <circle cx="50" cy="50" r="30" fill="red"></circle>
    </svg>
    <svg id="s3" draggable="yes" width="100" height="100">
      <circle cx="50" cy="50" r="30" fill="yellow"></circle>
    </svg>
  </div>
  <script type="text/javascript">
      var dragSourceElement = null;
      var dragTargetElement = null;
      function doDragStart(e){
          this.style.opacity = "0.4";
          this.style.border = "solid";
          dragSourceElement = this;
      }
      function doDragEnter(e){
          if(dragSourceElement != this){
             this.style.border = "dashed";
          } 
      }
      function doDragLeave(e){
          if(dragSourceElement != this){
              this.style.border = "";
          }
      }
      function doDragOver(e){
          if(dragSourceElement != this){
              dragTargetElement = this;
              e.preventDefault();//to allow a drop?
          }
      }
      function doDragEnd(e){
          this.style.border = "";
          this.style.opacity = "1.0";
      }
      function doDragDrop(e){
          if(dragSourceElement != dragTargetElement){
          dnd_svg(dragSourceElement,dragTargetElement);
          }
          dragSourceElement.style.border = "";
          dragTargetElement.style.border = "";
          dragSourceElement.style.opacity = "";
          dragSourceElement = null;
          dragTargetElement = null;
      }
      //called after a drag and drop
      //to insert svg element c1 before c2 in the DOM
      //subtree of the parent of c2, assuming c1 is 
      //dropped onto c2
      function dnd_svg(c1,c2){
        var parent_c2 = c2.parentElement;
        parent_c2.insertBefore(c1,c2);
      }
      function addL(n){
           n.addEventListener('dragstart',doDragStart,false);
           n.addEventListener('dragenter',doDragEnter,false);
           n.addEventListener('dragleave',doDragLeave,false);
           n.addEventListener('dragover',doDragOver,false);
           n.addEventListener('drop',doDragDrop,false);
      }
      addL(document.getElementById("s1"));
      addL(document.getElementById("s2"));
      addL(document.getElementById("s3"));
    </script>
</body>
</html>
4

2 に答える 2

0

この JSFiddleを参照してください。FF の SVG でのドラッグ アンド ドロップ イベントには問題があるため、1 つの解決策は SVG にラッパー要素を追加することです。これにより、dataTransfer メソッドを使用して、ノードをドロップ位置に追加できます。

<!DOCTYPE HTML>
<html>
    
   <head>
        <style type="text/css">
            #div1,#div2 {
                width:350px;
                height:70px;
                padding:10px;
                border:1px solid #aaaaaa;
            }
        </style>
        <script>
            function allowDrop(ev) {
                ev.preventDefault();
            }

            function drag(ev) {
                var id = ev.target ? ev.target.id : ev.srcElement.id;
                if (id === "circle") {
                    id = ev.target.parentNode.parentNode.id;
                }
                ev.dataTransfer.setData("Text", id);
            }

            function drop(ev) {
                ev.preventDefault();
                var data = ev.dataTransfer.getData("Text");
                ev.target.appendChild(document.getElementById(data));
            }
        </script>
    </head>
    
    <body>
       
        <div id="div1" ondrop="drop(event)"
        ondragover="allowDrop(event)"></div>
             <div id="div2" ondrop="drop(event)"
        ondragover="allowDrop(event)"></div>
        <br>
        <div id="wrapper" draggable="yes" ondragstart="drag(event)" style="width:100px; height:100px;">
            <svg id="svg" width="100" height="100" draggable="yes" ondragstart="drag(event)" >
                <circle id="circle" cx="50" cy="50" r="30" fill="yellow"></circle>
            </svg>
        </div>
    </body>

</html>

これは FF 18 と IE 9 の両方で機能します。厄介な部分は、FF と IE の両方がこれらのイベントの異なるターゲットをソースとしており、IE はドラッグ イベントのターゲットとして SVG を返しますが、FF は円を返します。とてもうるさい。

更新: Chrome 24 でこの JSFiddle を試してみましたが、動作します。

于 2013-01-20T20:22:57.447 に答える
0

このチュートリアルは、多くの例を使用して、ネイティブのドラッグ アンド ドロップを理解するのに非常に適しています。

ただし、SVG に関連する特定の問題がある場合があります。たとえば、このMozilla のバグを参照してください:「dragstart イベントが svg 要素で発生しません」。

于 2013-01-20T20:48:02.377 に答える