2013-01-20 26 views
5

Próbuję zmienić kolejność elementów DOM SVG przy użyciu natywnych zdarzeń przeciągania i upuszczania. Poniższy kod wydaje się działać (z dziwnymi efektami graficznymi) w Firefoksie, pracuj w Chrome w ograniczonej liczbie razy (dwa lub trzy razy remonty przeciągnij/upuść działają, a potem wydaje się, że się zawiesił), a niezbyt dobrze w IE. Domyślam się, że jest coś w tych wydarzeniach, o których nie myślę właściwie, jakiś rodzaj resetowania. A może korzystanie z przeciągania zdarzeń bez dataTransfer w ten sposób jest nieprawidłowe. Moim celem jest zrozumienie tego typu funkcji bez bibliotek, ale lepsze zrozumienie funkcji DOM, javascript, HTML i CSS na najbardziej podstawowym poziomie. Mogę łatwo popełnić błąd w dowolnym miejscu na tej liście.HTML5 przeciągnij i upuść manipulacja DOM za pomocą javascript

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

Zauważ, że istnieje błąd javascript w funkcji dnd_svg w IE9. var parent_c2 = c2.parentElement? c2.parentElement: c2.parentNode; rozwiązuje to dla mnie. Zobacz http://jsfiddle.net/nrNSS/. – stevebot

Odpowiedz

0

Zobacz this JSFiddle. Występuje problem z przeciąganiem i upuszczaniem zdarzeń na SVG w FF, więc jednym z rozwiązań jest dodanie elementu wrapper do SVG. Dzięki temu można użyć metody dataTransfer, a następnie dołączyć węzeł do miejsca upuszczenia.

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

Działa to dla mnie zarówno w IE i FF 18 9. irytujące jest to, że FF i IE zarówno źródłowe różne cele dla tych wydarzeń, z IE zwrotu SVG jako cel na razie oporu, natomiast FF zwraca okrąg. Bardzo irytujące.

Aktualizacja: próbowałem tego JSFiddle w Chrome 24 i to działa.

+0

Cześć, dziękuję - moim głównym celem było sprawdzenie, czy mógłbym użyć zdarzeń przeciągnij i upuść, aby wymieszać elementy svg, po prostu proste uporządkowanie. Ostatecznie myślę, że odpowiedź może nie polegać na dragowaniu i upuszczaniu HTML5 w tym celu. –

0

Ten model tutorial jest całkiem niezły w zrozumieniu natywnego przeciągania i upuszczania, z wieloma przykładami.

Jednak mogą występować szczególne problemy związane z SVG. Zobacz na przykład ten Mozilla bug: "zdarzenie dragstart nie jest uruchamiane na elemencie svg".

+0

Cześć, dziękuję, zapoznałem się z tym samouczkiem, kiedy to rozpocząłem. Ale to dobre połączenie. –

Powiązane problemy