Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a SVG Text draggable using d3.js

I want to make a text in a d3 visualisation draggable for use in an editor. I started to play with on e of the examples (http://bl.ocks.org/mbostock/4063550). When i add a dragbeheavier to the text element, i can tell from the ChromeDevTools that somthing gets dragged but there is no visual representation af that drag. I also tried to do it using JQuery UI what didn't worked either. What do i miss and is it even possible to do so?

like image 240
chenninger Avatar asked Apr 30 '13 07:04

chenninger


2 Answers

You can use drag.behaviour to add drag events to elements.

1) Create a function to handle the drag event (of type d3.event):

function dragmove(d) {
    d3.select(this)
      .style("top", ((d3.event.sourceEvent.pageY) - this.offsetHeight/2)+"px")
      .style("left", ((d3.event.sourceEvent.pageX) - this.offsetWidth/2)+"px")
}

2) Create drag behavior using the above function as handler:

var drag = d3.behavior.drag()
    .on("drag", dragmove);

3) Bind it to an element or a set of elements using .call on a d3 selection:

d3.select("body").append("div")
    .attr("id", "draggable")
    .text("Drag me bro!")
    .call(drag)

Try it: http://jsfiddle.net/HvkgN/2/

Here's the same example, adapted for an svg text element:

function dragmove(d) {
    d3.select(this)
      .attr("y", d3.event.y)
      .attr("x", d3.event.x)
}

var drag = d3.behavior.drag()
    .on("drag", dragmove);

d3.select("body").append("svg")
    .attr("height", 300)
    .attr("width", 300)
    .append("text")
        .attr("x", 150)
        .attr("y", 150)
        .attr("id", "draggable")
        .text("Drag me bro!")
        .call(drag)
like image 171
minikomi Avatar answered Nov 14 '22 21:11

minikomi


A better-looking way to add dragging to an SVG element is to use a translate transform that moves the draggable element around. Couple this with a drag event handler that uses d3.event.dx and d3.event.dy to monitor the mouse's movement.

var transX = 0;
var transY = 0;
var theElement = d3.select('svg#xyz text.blahblah').attr('transform', "translate(" + transX + ", " + transY + ")");

var repositionElement = function(data) {
    transX += d3.event.dx;
    transY += d3.event.dy;
    theElement.attr('transform', "translate(" + transX + ", " + transY + ")");
};

var addDragging = function (element) {
    element.call(d3.behavior.drag().on('drag', repositionElement));
};

addDragging(theElement);

Also, unlike changing x/y directly, this technique can be used to make an entire <g> group draggable, so when the user clicks and drags any part of the group, the whole group moves!

like image 2
Ian Durkan Avatar answered Nov 14 '22 20:11

Ian Durkan