将SVG元素拖动到另一个SVG元素上

Dragging SVG element over another SVG element

本文关键字:元素 SVG 另一个 拖动      更新时间:2023-09-26

有什么方法可以将SVG元素拖动到另一个SVG元素上吗?我试过了,但就像在本教程中一样,我只能把我放在第二个上面的那个拖到第一个上面。我不可能毫无问题地把第一个拖过第二个。有人知道怎么解决这个问题吗?

以下是整个教程:http://www.petercollingridge.co.uk/book/export/html/437

我在看到@Strat-O给你同样的方法之前就已经在写了。

下面是一个有评论的例子:

<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="200">
    
    <style>
      .draggable {
        cursor: move;
      }
    </style>
    
    <script type="text/ecmascript"><![CDATA[
    var selectedElement = 0;
    var currentX = 0;
    var currentY = 0;
    var currentMatrix = 0;
	function cloneToTop(oldEl){
	  // already at top, don't go farther…
	  if(oldEl.atTop==true) return oldEl;
	  // make a copy of this node
	  var el = oldEl.cloneNode(true);
 	  // select all draggable elements, none of them are at top anymore
	  var dragEls= oldEl.ownerDocument.documentElement.querySelectorAll('.draggable');
	  for(i=0; i<dragEls.length; i++){
	  	dragEls[i].atTop=null;
	  	}
	  var parent = oldEl.parentNode;
	  // remove the original node
	  parent.removeChild(oldEl);
	  // insert our new node at top (last element drawn is first visible in svg)
  	  parent.appendChild(el);
  	  // Tell the world that our new element is at Top
	  el.atTop= true;
	  return el;
	  }
    function selectElement(evt) {
      selectedElement = cloneToTop(evt.target);
      currentX = evt.clientX;
      currentY = evt.clientY;
      currentMatrix = selectedElement.getAttributeNS(null, "transform").slice(7,-1).split(' ');
    
      for(var i=0; i<currentMatrix.length; i++) {
        currentMatrix[i] = parseFloat(currentMatrix[i]);
      }
      
      selectedElement.setAttributeNS(null, "onmousemove", "moveElement(evt)");
      selectedElement.setAttributeNS(null, "onmouseout", "deselectElement(evt)");
      selectedElement.setAttributeNS(null, "onmouseup", "deselectElement(evt)");
    }
        
    function moveElement(evt) {
      var dx = evt.clientX - currentX;
      var dy = evt.clientY - currentY;
      currentMatrix[4] += dx;
      currentMatrix[5] += dy;
      
      selectedElement.setAttributeNS(null, "transform", "matrix(" + currentMatrix.join(' ') + ")");
      currentX = evt.clientX;
      currentY = evt.clientY;
    }
        
    function deselectElement(evt) {
      if(selectedElement != 0){
          selectedElement.removeAttributeNS(null, "onmousemove");
          selectedElement.removeAttributeNS(null, "onmouseout");
          selectedElement.removeAttributeNS(null, "onmouseup");
          selectedElement = 0;
          }
        }
        
    ]]> </script>
    <g>
    <circle/>
    </g>
    <rect x="0.5" y="0.5" width="399" height="199" fill="none" stroke="black"/>
    
    <rect class="draggable" id="blue" x="30" y="30" width="80" height="80" fill="blue" transform="matrix(1 0 0 1 46 18)" onmousedown="selectElement(evt)"/>
          
    <rect class="draggable" id="green" x="160" y="50" width="50" height="50" fill="green" transform="matrix(1 0 0 1 51 11)" onmousedown="selectElement(evt)"/>
</svg>

不幸的是,在SVG中,只有一种方法可以使一个元素出现在另一个元素的前面,那就是移除较低的元素,然后转身重新绘制它。您无法设置z索引或其他有用的属性。我在这方面花了一些时间,这就是我的结论。

有一个好处,那就是通过删除和重新绘制它,它可以确保所有元素的显示顺序都得到维护,而如果必须维护z索引,管理数字可能会导致一系列问题。