使用JQuery和Jquery-svg拖动SVG

我有一个HTML 5页面,我加载了一个svg圈子。 当我点击圈子时,我点击了另一个小圈子。 我想能够拖动第二个圆,但似乎不能用jquery-ui .draggable();

我可以通过访问它的cx和cy属性来移动这个圆,所以必须有一种方法来拖动它。

<!DOCTYPE HTML> <html > <head> <title></title> <link href="css/reset.css" rel="stylesheet" type="text/css"> <link href="css/layout.css" rel="stylesheet" type="text/css"> <link href="css/style.css" rel="stylesheet" type="text/css"> <script src="js/jquery.js" type="text/javascript" ></script> <script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script> <script src="js/jquery-ui.js" type="text/javascript" ></script> <script type="text/javascript" > jQuery(document).ready(function(){ $('#target').svg({onLoad: drawInitial}); $('circle').click(function(e){ drawShape(e); var shape = this.id; }); $('.drag').mousedown(function(e){ var shape = this.id; this.setAttribute("cx", e.pageX); this.setAttribute("cy", e.pageY); }); }) function drawInitial(svg) { svg.add($('#svginline')); } function drawShape(e) { var svg = $("#target").svg('get'); $('#result').text(e.clientX + ": " + e.pageX); var dragme = svg.circle(e.clientX, e.clientY, 5, {fill: 'green', stroke: 'red', 'stroke-width': 3, class_: 'drag'}); //$(dragme).draggable(); } </script> </head> <body> <div id="target" ></div> <svg:svg id="svginline"> <svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/> </svg:svg> <div id="result" >ffff</div> </body> </html> 

jQuery UI可拖动行为确实可行,但是您需要在拖动处理程序中手动更新位置,因为相对CSS定位在SVG内不起作用。

 svg.rect(20,10,100,50, 10, 10, {fill:'#666'}); svg.rect(40,20,100,50, 10, 10, {fill:'#999'}); svg.rect(60,30,100,50, 10, 10, {fill:'#ccc'}); $('rect') .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); }); 

我正在修补的解决scheme涉及到(将其与您的案例绑定)创build一个新的div和svg,定位在原始形状,作为目标svg对象的句柄。 使句柄可拖动,并存储起始顶部/左侧偏移量(认为隐藏div)。 一旦可拖动div的“停止”事件被触发,找出顶部和左侧的变化程度(stopX-startX = changeX)并将其应用于原始形状坐标。 然后,删除()你的临时形状。

这个链接对如何解决一般问题(即不需要JQuery)有很好的描述,这绝对是我见过的最好的解决scheme。 不过,我想继续使用JQuery的优秀的Draggable API。

我最近花了几天时间来解决这个问题。 上面接受的答案是我第一次尝试,但我不能让它在Firefox中正常工作。 浏览器如何处理 SVG坐标有些不同。

我提出了一个解决scheme,在Chrome和Firefox中都能很好地工作,并让我继续使用JQuery UI。 我没有在任何地方进行testing。 这绝对是一个黑客。

你可以在这里看到我在小提琴上所做的一个快速的模拟。 关键的想法是使用一个代理div,你一直在你想拖动的svg元素上方盘旋。 然后在拖动代理div时,更改svg元素的x和y坐标。 像这样的东西:

 $('#proxy').on('drag', function(e) { t = $('#background'); prox = $('#proxy'); t.attr('x', t.attr('x')*1 + prox.css('left').slice(0,-2)*1 - prox.data('position').left) .attr('y', t.attr('y')*1 + prox.css('top').slice(0,-2)*1 - prox.data('position').top); prox.data('position',{top : prox.css('top').slice(0,-2)*1, left: prox.css('left').slice(0,-2)*1} ); }); 

在我的情况下,我想要拖动的SVG元素将始终填满屏幕上的某个正方形,所以很容易将代理div放在目标上。 在其他情况下,这可能会困难得多。 使用“遏制”选项也不难,不要在框架之外拖动背景……只需要一些小心的math计算,并且必须在每次拖动之间重置遏制。

为了使其适用于更多的SVG元素,可以使用变换而不是x和y坐标。

我创build了一个基本的拖放function来定位我的SVG对象。 我没有任何遏制或碰撞检测。 有一个问题,如果我太移动鼠标太quicly我会离开拖动对象。

 <!DOCTYPE HTML> <html > <head> <title></title> <link href="css/reset.css" rel="stylesheet" type="text/css"> <link href="css/layout.css" rel="stylesheet" type="text/css"> <link href="css/style.css" rel="stylesheet" type="text/css"> <script src="js/jquery.js" type="text/javascript" ></script> <script src="js/jquery-ui.js" type="text/javascript" ></script> <script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script> <script src="js/jquerysvg/jquery.svgdom.js" type="text/javascript" ></script> <script type="text/javascript" > jQuery(document).ready(function(){ $('#target').svg({onLoad: drawInitial}); $('circle').click(function(e){ drawShape(e); var shape = this.id; }); }) function drawInitial(svg) { svg.add($('#svginline')); } function onMouseDown(evt){ //var shape = this.id; var target = evt.target; target.onmousemove = onMouseMove; return false; } function onMouseMove(evt){ circle = evt.target var cx = circle.getAttribute("cx"); offsetX = $('#target').offset().left; offsetY = $('#target').offset().top circle.setAttribute("cx", evt.clientX -offsetX); circle.setAttribute("cy", evt.clientY - offsetY); circle.onmouseup = OnMouseUp; } function OnMouseUp(evt) { var target = evt.target; target.onmousemove = null; } function drawShape(e) { var svg = $("#target").svg('get'); offsetX = $('#target').offset().left; offsetY = $('#target').offset().top; $('#result').text(e.clientX + ": " + e.pageX); var dragme = svg.circle(e.clientX - offsetX, e.clientY - offsetY, 5, {onmousedown: "onMouseDown(evt)",fill: 'green', stroke: 'red', 'stroke-width': 3}); $(dragme).addClass('drag'); } </script> </head> <body> <div id="target" ></div> <svg:svg id="svginline"> <svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/> </svg:svg> <div id="result" >ffff</div> </body> </html>