使用javascript进行HTML5拖放DOM操作

使用javascript进行HTML5拖放DOM操作,javascript,html,dom,javascript-events,Javascript,Html,Dom,Javascript Events,我试图使用本机拖放事件对DOM SVG元素重新排序。下面的代码在Firefox中似乎可以工作(带有一些奇怪的图像效果),在Chrome中可以工作有限的次数(2次或3次拖放重新排序可以工作,然后它似乎挂起),在IE中也不是很好。我最好的猜测是,关于所讨论的事件,我没有正确思考,某种类型的重置。或者,以这种方式使用没有数据传输的拖动事件是不正确的。我的目标是在没有库的情况下理解这种类型的函数,但是在最基本的层次上更清楚地理解DOM函数、javascript、HTML和CSS。在那张单子上的任何地方,

我试图使用本机拖放事件对DOM SVG元素重新排序。下面的代码在Firefox中似乎可以工作(带有一些奇怪的图像效果),在Chrome中可以工作有限的次数(2次或3次拖放重新排序可以工作,然后它似乎挂起),在IE中也不是很好。我最好的猜测是,关于所讨论的事件,我没有正确思考,某种类型的重置。或者,以这种方式使用没有数据传输的拖动事件是不正确的。我的目标是在没有库的情况下理解这种类型的函数,但是在最基本的层次上更清楚地理解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>

拖放实验
svg{边框宽度:3px}
var dragSourceElement=null;
var dragTargetElement=null;
功能启动(e){
this.style.opacity=“0.4”;
this.style.border=“solid”;
dragSourceElement=此;
}
功能输入(e){
if(dragSourceElement!=此){
this.style.border=“虚线”;
} 
}
函数(e){
if(dragSourceElement!=此){
this.style.border=“”;
}
}
函数doDragOver(e){
if(dragSourceElement!=此){
dragTargetElement=此;
e、 preventDefault();//是否允许删除?
}
}
函数doDragEnd(e){
this.style.border=“”;
this.style.opacity=“1.0”;
}
函数doDragDrop(e){
if(dragSourceElement!=dragTargetElement){
dnd_svg(dragSourceElement,dragTargetElement);
}
dragSourceElement.style.border=“”;
dragTargetElement.style.border=“”;
dragSourceElement.style.opacity=“”;
dragSourceElement=null;
dragTargetElement=null;
}
//拖放后调用
//在DOM中的c2之前插入svg元素c1
//c2父级的子树,假设c1为
//降落到c2
功能dnd_svg(c1、c2){
var parent_c2=c2.parentElement;
父项c2.insertBefore(c1,c2);
}
函数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”);
请参阅。FF中SVG上的拖放事件存在问题,因此一种解决方案是向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>

#第1部分,第2部分{
宽度:350px;
高度:70像素;
填充:10px;
边框:1px实心#AAAAA;
}
功能allowDrop(ev){
ev.preventDefault();
}
功能阻力(ev){
var id=ev.target?ev.target.id:ev.srceelement.id;
如果(id==“圆圈”){
id=ev.target.parentNode.parentNode.id;
}
ev.dataTransfer.setData(“文本”,id);
}
功能下降(ev){
ev.preventDefault();
var data=ev.dataTransfer.getData(“文本”);
ev.target.appendChild(document.getElementById(数据));
}

这在FF 18和IE 9中都适用。令人恼火的是FF和IE都为这些事件提供了不同的目标,IE返回SVG作为拖动事件的目标,而FF返回圆圈。很烦人

更新:我在Chrome 24中试用了这个JSFIDLE,它很管用。

这对于理解本机拖放非常有用,有很多例子


但是,可能存在与SVG相关的特定问题。例如,请参见:“dragstart事件未在svg元素上触发”。

注意,IE9中的dnd_svg函数中存在javascript错误。var parent_c2=c2.parentElement?c2.parentElement:c2.parentNode;帮我解决。您好,谢谢,我刚开始写这篇文章的时候已经看过了。但是这是一个很好的链接。嗨,谢谢-我的主要目标是尝试看看是否可以使用拖放事件来洗牌svg元素,只需简单的重新排序。最终,我认为答案可能是不要为此目的使用HTML5拖放。