SVG se puede arrastrar usando JQuery y Jquery-svg

Tengo una página HTML 5 donde cargo un círculo svg. Cuando hago clic en el círculo, creo otro pequeño círculo donde hago clic. Quiero poder arrastrar el segundo círculo, pero no puedo hacerlo con jquery-ui .draggable ();

Puedo mover el círculo accediendo a sus atributos cx y cy, así que debe haber una forma de arrastrarlo.

           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(); }    
ffff

El comportamiento de jQuery UI que se puede arrastrar funciona, pero debes actualizar la posición manualmente en el controlador de arrastre, ya que el posicionamiento relativo de CSS no funciona dentro de 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); }); 

La solución con la que estoy retocando implica (para vincularla a su caso) crear un nuevo div y svg, posicionado sobre la forma original, para actuar como el manipulador del objeto svg específico. Haga que el controlador div se pueda arrastrar y guarde el desplazamiento superior / izquierdo inicial externamente (piense en div oculto). Una vez que se dispara el evento “stop” para el div arrastrable, determine el grado de cambio para la parte superior e izquierda (stopX-startX = changeX) y aplíquelo a las coordenadas de formas originales. Entonces. Retire () su forma temporal.

Este enlace tiene una excelente descripción de cómo resolver el problema en general (es decir, sin requerir JQuery), y esa es definitivamente la mejor solución que he visto. Sin embargo, quería seguir usando la excelente API Draggable de JQuery.

Recientemente, pasé un par de días martilleando sobre este problema. La respuesta aceptada anteriormente es lo que intenté primero, pero no pude hacer que funcionara correctamente en Firefox. Hay algo acerca de cómo los navegadores manejan las coordenadas SVG de manera diferente.

Se me ocurrió una solución que funcionó bastante bien para mí, tanto en Chrome como en Firefox, y me permite seguir usando la interfaz de usuario de JQuery. No lo he probado en todas partes. Definitivamente es un truco.

Puedes ver una maqueta rápida de lo que hice en un violín aquí . La idea clave es usar un proxy div que sigas desplazándote exactamente sobre el elemento svg que deseas arrastrar. A continuación, cambie las coordenadas xey del elemento svg a medida que arrastra el div proxy. Algo como esto:

 $('#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} ); }); 

En mi caso, el elemento SVG que quería arrastrar siempre llenaría un cierto cuadrado en la pantalla, por lo que era muy fácil posicionar el div proxy sobre el objective. En otras situaciones, podría ser mucho más difícil. Tampoco es demasiado difícil usar la opción de ‘contención’ para asegurarte de que no arrastras el fondo fuera del marco … solo requiere una cuidadosa operación matemática y debes restablecer la contención entre cada arrastre.

Para que esto sea aplicable a más elementos SVG, puede usar transformaciones en lugar de coordenadas xey.

Creé una función básica de arrastrar y soltar para apuntar a mis objetos svg. No tengo ninguna detección de contención o colisión. Existe un problema si muevo el mouse demasiado rápido. Dejo atrás el objeto que se puede arrastrar.

 < !DOCTYPE HTML>              
ffff