如何启动SVG从其原始位置拖动

时间:2014-02-03 08:59:39

标签: jquery svg jquery-ui-draggable

我有以下代码来拖动svg对象。

$('#svg-drag')
   .draggable()
   .bind('mousedown', function(event, ui){
    // bring target to front
    $(event.target.parentElement).append( event.target );
   })
   .bind('drag', function(event, ui){
    // update coordinates manually, since top/left style props don't work on SVG
    event.target.setAttribute('x', ui.position.left);
    event.target.setAttribute('y', ui.position.top);

});

但是当我开始拖动对象时,它总是从角落开始。使用0,0 xy坐标。我想从它的原始坐标开始拖动。如果我有100,300 xy坐标,我想从100 x坐标和300 y坐标开始拖动。

提前致谢!!

3 个答案:

答案 0 :(得分:1)

当拖动开始时,即鼠标按下时,您必须能够访问其当前的x,y平移值。这在下面的示例中显示为OffsetX,OffsetY值

此示例使用Javascript。我想这个例子可能比你现在要求的更多...但希望它能在将来为你提供拖放svg元素的能力。

它解决了任何svg元素的拖放问题,无论它以前的转换和/或viewPorts。它使用SVGPoint作为拖动参考,因此无需访问元素的位置属性。我称之为 SVG Universal Drag / Drop ;)

此外,它不需要将元素移动到顶部来拖动它们。这可能与所需的布局冲突,除非它们在拖动端返回。

此示例使用SVG矩阵变换,使用对象方法,而不是变换字符串。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>SVG Universal Drag/Drop</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>SVG Universal Drag/Drop</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
This example uses matrix transforms, with object methods,  not strings. It can seamlessly drag/drop elements that have previously been transformed and reside it different viewPorts. It employs <b>getScreenCTM</b>,  <b>createSVGTransform</b> and attaches the element to a <b>transform List</b>
</div>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400"  onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag()>
<circle id="redCircle" cx="120" cy="180" r="40" fill="red" stroke="black" stroke-width="2" />
<circle  id="orangeCircle" cx="200" cy="200" r="40" fill="orange" stroke="black" stroke-width="2" />
<svg viewBox="0 100 800 800">
<rect id="maroonRect"  x="220" y="250" width="60" height="60" fill="maroon" stroke="black" stroke-width="2"  />
</svg>
<g id="myG" >
<rect  id="blueRect"  x="220" y="250" width="60" height="60" fill="blue" stroke="black" stroke-width="2"  />
</g>
</svg>
</div>
</center>
<script id=myScript>
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var OffsetX = 0;
var OffsetY = 0;
//---mouse down over element---
function startDrag(evt)
{
    if(!Dragging) //---prevents dragging conflicts on other draggable elements---
    {
        DragTarget = evt.target;
        //---reference point to its respective viewport--
        var pnt = DragTarget.ownerSVGElement.createSVGPoint();
        pnt.x = evt.clientX;
        pnt.y = evt.clientY;
        //---elements transformed and/or in different(svg) viewports---
        var sCTM = DragTarget.getScreenCTM();
        var Pnt = pnt.matrixTransform(sCTM.inverse());

        TransformRequestObj = DragTarget.ownerSVGElement.createSVGTransform()
        //---attach new or existing transform to element, init its transform list---
        var myTransListAnim=DragTarget.transform
        TransList=myTransListAnim.baseVal

        OffsetX = Pnt.x
        OffsetY = Pnt.y

        Dragging=true;
     }
}
//---mouse move---
function drag(evt)
{
    if(Dragging)
    {
        var pnt = DragTarget.ownerSVGElement.createSVGPoint();
        pnt.x = evt.clientX;
        pnt.y = evt.clientY;
        //---elements in different(svg) viewports, and/or transformed ---
        var sCTM = DragTarget.getScreenCTM();
        var Pnt = pnt.matrixTransform(sCTM.inverse());
        Pnt.x -= OffsetX;
        Pnt.y -= OffsetY;

        TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
        TransList.appendItem(TransformRequestObj)
        TransList.consolidate()
    }
}
//--mouse up---
function endDrag()
{
    Dragging = false;
}

document.addEventListener("onload",initTransforms(),false)
//---onload---
function initTransforms()
{
//---place some transforms on the elements---

    //--- transform orange circle---
    var transformRequestObj=mySVG.createSVGTransform()
    var animTransformList=orangeCircle.transform
    var transformList=animTransformList.baseVal
    //---translate---
    transformRequestObj.setTranslate(180,-260)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----scale---
    transformRequestObj.setScale(.5,.9)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewY---
    transformRequestObj.setSkewY(52)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()

    //--init Transform on myG---
    var transformRequestObj=mySVG.createSVGTransform()
    var animTransformList=myG.transform
    var transformList=animTransformList.baseVal
    //---translate---
    transformRequestObj.setTranslate(-50,-80)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewX---
    transformRequestObj.setSkewX(15)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewY---
    transformRequestObj.setSkewY(20)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //---rotate---
    transformRequestObj.setRotate(30,200,200)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
}
</script>
</body>
</html>

答案 1 :(得分:0)

这里尝试这个例子,

<div id="containment-wrapper" class="wrap">


    <svg id="svg-drag" width="100" height="100">
   <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
   Sorry, your browser does not support inline SVG.
</svg>

</div>

<强> Jquery的:

$('#svg-drag')
   .draggable()
   .bind('mousedown', function(event, ui){
    // bring target to front
    $(event.target.parentElement).append( event.target );
   })
   .bind('drag', function(event, ui){
    // update coordinates manually, since top/left style props don't work on SVG
    event.target.setAttribute('x', ui.position.left);
    event.target.setAttribute('y', ui.position.top);
});

演示fiddle

答案 2 :(得分:0)

如果您已转换路径,则以下内容将更新其d属性并删除转换。 Thiis适用于所有svg路径类型,弧除外。

//---except arc paths---
function screenPath(path)
{
    var sCTM = path.getCTM()
    var svgRoot = path.ownerSVGElement

    var segList=path.pathSegList
    var segs=segList.numberOfItems
    //---change segObj values
    for(var k=0;k<segs;k++)
    {
        var segObj=segList.getItem(k)

        if(segObj.x && segObj.y )
        {
            var mySVGPoint = svgRoot.createSVGPoint();
            mySVGPoint.x = segObj.x
            mySVGPoint.y = segObj.y
            mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
            segObj.x=mySVGPointTrans.x
            segObj.y=mySVGPointTrans.y
        }

        if(segObj.x1 && segObj.y1)
        {
            var mySVGPoint1 = svgRoot.createSVGPoint();
            mySVGPoint1.x = segObj.x1
            mySVGPoint1.y = segObj.y1
            mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
            segObj.x1=mySVGPointTrans1.x
            segObj.y1=mySVGPointTrans1.y
        }
        if(segObj.x2 && segObj.y2)
        {
            var mySVGPoint2 = svgRoot.createSVGPoint();
            mySVGPoint2.x = segObj.x2
            mySVGPoint2.y = segObj.y2
            mySVGPointTrans2 = mySVGPoint2.matrixTransform(sCTM)
            segObj.x2=mySVGPointTrans2.x
            segObj.y2=mySVGPointTrans2.y
        }


    }
    //---force removal of transform--
    path.setAttribute("transform","")
    path.removeAttribute("transform")
}