2014-04-01 92 views
1

我目前正在研究一个应用程序,该应用程序支持使用此code拖放&拖放来拖放&拖放。问题是我需要相应地移动连接的线,我不知道如何获取X和Y坐标来更改x1/y1对或x2/y2对来更新线。翻译元素的位置

我已经尝试过使用其边界框询问元素的位置,并且数字与拖动&下降后的实际位置不匹配。

任何想法我怎么能做到这一点? (给出代码中计算的信息,上面链接)

+0

你可以发布jsfiddle吗? – Ian

回答

1

与转换元素的BBox不同,您可以将元素插入到SVG“包装器”中,然后获取该元素的bbox。

我重写了您的示例并添加到了HTML5文档。我包括一个svg包装器元素,并且每个圆圈的中心附有三条线。当它拖动时,线条随之而来。 这如下所示。 (注:Chrome挂在文本元素上)

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Drag And Drop</title> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
</head> 
<body style='padding:10px;font-family:arial'> 
<center> 
<h4>Drag And Drop</h4> 
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'> 
    A nice little demo of drag-and-drop functionality in SVG, 
     written by Doug Schepers on February 16, 2004. 
     Use or misuse this code however you wish.</div> 
<table><tr> 

<td> 
<div id="svgDiv" style='background-color:lightgreen;width:600px;height:300px;'> 
<svg width='100%' height='100%' xmlns='http://www.w3.org/2000/svg' id="mySVG" 
    onload='Init(evt)' 
    onmousedown='Grab(evt)' 
    onmousemove='Drag(evt)' 
    onmouseup='Drop(evt)'> 
    <rect id='BackDrop' x='-10%' y='-10%' width='110%' height='110%' fill='none' pointer-events='all' /> 

    <circle id='BlueCircle' cx='25' cy='25' r='20' style='fill:blue; '/> 
    <circle id='RedCircle' cx='125' cy='25' r='20' style='fill:red; '/> 
    <circle id='OrangeCircle' cx='225' cy='25' r='20' style='fill:orange; '/> 

    <text id='DraggableText' x='20' y='200' style='fill:red; font-size:18px; font-weight:bold;'>Draggable Text</text> 


    <rect id='GreenRectangle' x='50' y='70' width='100' height='100' style='fill:green; '/> 

    <g id='Folder'> 
     <rect id='FolderRectangle' x='300' y='100' width='200' height='150' style='fill:tan; stroke:brown; stroke-width:3;'/> 
    </g> 

    <svg id="Wrapper" /> 
<line id=blueLine stroke=blue stroke=3 x1=25 y1=25 x2=25 y2=25 /> 
<line id=redLine stroke=red stroke=3 x1=125 y1=25 x2=125 y2=25 /> 
<line id=orangeLine stroke=orange stroke=3 x1=225 y1=25 x2=225 y2=25 /> 

</svg> 
</div> 

</td> 
</tr></table> 
    <br />SVG Source:<br /> 
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea> 
    <br />Javascript:<br /> 
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea> 
</center> 
<div id='browserDiv' style='padding:5px;position:absolute;top:5px;left:5px;background-color:gainsboro;'>OK in:IE11/FF23...*CH hangs<br /></div> 
<script id=myScript> 
     //var SVGDocument = null; 
     //var SVGRoot = null; 

     var TrueCoords = null; 
     var GrabPoint = null; 
     var BackDrop = null; 
     var DragTarget = null; 
     var DragLine = null; 

     function Init(evt) 
     { 
     //SVGDocument = evt.target.ownerDocument; 
     //SVGRoot = SVGDocument.documentElement; 

     // these svg points hold x and y values... 
     // very handy, but they do not display on the screen (just so you know) 
     TrueCoords = mySVG.createSVGPoint(); 
     GrabPoint = mySVG.createSVGPoint(); 

     // this will serve as the canvas over which items are dragged. 
     // having the drag events occur on the mousemove over a backdrop 
     // (instead of the dragged element) prevents the dragged element 
     // from being inadvertantly dropped when the mouse is moved rapidly 
     // BackDrop = SVGDocument.getElementById('BackDrop'); 
     } 

     function Grab(evt) 
     { 
     // find out which element we moused down on 
     var targetElement = evt.target; 

     // you cannot drag the background itself, so ignore any attempts to mouse down on it 
     if (BackDrop != targetElement) 
     { 
      //set the item moused down on as the element to be dragged 
      DragTarget = targetElement; 
      Wrapper.appendChild(DragTarget) 

      if(DragTarget.id=="BlueCircle") 
      DragLine=blueLine 
      if(DragTarget.id=="RedCircle") 
      DragLine=redLine 
      if(DragTarget.id=="OrangeCircle") 
      DragLine=orangeLine 

      // move this element to the "top" of the display, so it is (almost) 
      // always over other elements (exception: in this case, elements that are 
      // "in the folder" (children of the folder group) with only maintain 
      // hierarchy within that group 
      DragTarget.parentNode.appendChild(DragTarget); 

      // turn off all pointer events to the dragged element, this does 2 things: 
      // 1) allows us to drag text elements without selecting the text 
      // 2) allows us to find out where the dragged element is dropped (see Drop) 
      DragTarget.setAttributeNS(null, 'pointer-events', 'none'); 

      // we need to find the current position and translation of the grabbed element, 
      // so that we only apply the differential between the current location 
      // and the new location 
      var transMatrix = DragTarget.getCTM(); 
      GrabPoint.x = TrueCoords.x - Number(transMatrix.e); 
      GrabPoint.y = TrueCoords.y - Number(transMatrix.f); 

     } 
     }; 


     function Drag(evt) 
     { 
     // account for zooming and panning 
     GetTrueCoords(evt); 

     // if we don't currently have an element in tow, don't do anything 
     if (DragTarget) 
     { 
      // account for the offset between the element's origin and the 
      // exact place we grabbed it... this way, the drag will look more natural 
      var newX = TrueCoords.x - GrabPoint.x; 
      var newY = TrueCoords.y - GrabPoint.y; 
       BB=Wrapper.getBBox() 
      var bbx=BB.x 
      var bby=BB.y 
      var bbw=BB.width 
      var bbh=BB.height 
      Cx=bbx+.5*bbw 
      Cy=bby+.5*bbh 
      DragLine.x2.baseVal.value=Cx 
      DragLine.y2.baseVal.value=Cy 
      // apply a new tranform translation to the dragged element, to display 
      // it in its new location 
      DragTarget.setAttributeNS(null, 'transform', 'translate(' + newX + ',' + newY + ')'); 
     } 
     }; 


     function Drop(evt) 
     { 
     // if we aren't currently dragging an element, don't do anything 
     if (DragTarget) 
     {  mySVG.appendChild(DragTarget) //--remove from Wrapper--- 
      // since the element currently being dragged has its pointer-events turned off, 
      // we are afforded the opportunity to find out the element it's being dropped on 
      var targetElement = evt.target; 

      // turn the pointer-events back on, so we can grab this item later 
      DragTarget.setAttributeNS(null, 'pointer-events', 'all'); 
      if ('Folder' == targetElement.parentNode.id) 
      { 
       // if the dragged element is dropped on an element that is a child 
       // of the folder group, it is inserted as a child of that group 
       targetElement.parentNode.appendChild(DragTarget); 
       //alert(DragTarget.id + ' has been dropped into a folder, and has been inserted as a child of the containing group.'); 
      } 
      else 
      { 
       // for this example, you cannot drag an item out of the folder once it's in there; 
       // however, you could just as easily do so here 
       //alert(DragTarget.id + ' has been dropped on top of ' + targetElement.id); 
      } 

      // set the global variable to null, so nothing will be dragged until we 
      // grab the next element 
      DragTarget = null; 
     } 


      svgSourceValue.value=svgDiv.innerHTML 
     }; 


     function GetTrueCoords(evt) 
     { 
     // find the current zoom level and pan setting, and adjust the reported 
     // mouse position accordingly 
     var newScale = mySVG.currentScale; 
     var translation = mySVG.currentTranslate; 
     TrueCoords.x = (evt.clientX - translation.x)/newScale; 
     TrueCoords.y = (evt.clientY - translation.y)/newScale; 
     }; 


</script> 
<script> 
document.addEventListener("onload",init(),false) 
function init() 
{ 
    svgSourceValue.value=svgDiv.innerHTML 
    jsValue.value=myScript.text 
} 
</script> 

</body> 

</html> 
+0

谢谢,那正是我需要的 –