How to set the Origin (drag.origin) for drag behavior in d3 JavaScript library

d3.js, drag, javascript

Solution

You simply need to set the `origin()` function accordingly. In the second case this is straightforward, in the first case somewhat more difficult because you are using coordinates as well as a transform. The basic pattern (for the second case) looks like this:

 .origin(function() { 
        var t = d3.select(this);
        return {x: t.attr("x"), y: t.attr("y")};
    })

Updated jsfiddle here.

Problem

I am trying to implement drag behavior for group consisting from HTML-text and background-rectangle using the d3 framework. I was able to get it working, although when not setting the drag.origin I can see noticeable jump due to the mouse-position/element-coordinates offset. Exactly how described on the d3 wiki-page Although the page described how to set the Origin for dragging, I do not properly understand how ti implement it in my example. I tried two different approaches : using the element for grouping the elements together and defining new element holding tose. In the first case I have to use the translate-function and I do not even know how to get the coordinates of the group. ``` var svg = d3.select("body").append("svg") .attr("width", 960) .attr("height", 500); var group = svg.append("svg:g") .attr("transform", "translate(10, 10)") .attr("id", "group"); var rect1 = group.append("svg:rect") .attr("rx", 6) .attr("ry", 6) .attr("x", 5/2) .attr("y", 5/2) .attr("id", "rect") .attr("width", 250) .attr("height", 125) .style("fill", 'white') .style("stroke", d3.scale.category20c()) .style('stroke-width', 5); var html1 = group.append("foreignObject") .attr("x", 50) .attr("y", 25) .attr("width", 200) .attr("height", 100) .attr("id", "fobject") .style("border-color", d3.scale.category20c()) .append("xhtml:div") .style("font", "14px 'Helvetica Neue'") .html("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam."); var innerSvg = svg.append("svg") .attr("x", 500) .attr("y", 10) .attr("id", "innerSvg"); var rect2 = innerSvg.append("svg:rect") .attr("rx", 6) .attr("ry", 6) .attr("x", 5/2) .attr("y", 5/2) .attr("id", "rect") .attr("width", 250) .attr("height", 125) .style("fill", 'white') .style("stroke", d3.scale.category20c()) .style('stroke-width', 5); var html2 = innerSvg.append("foreignObject") .attr("x", 50) .attr("y", 25) .attr("width", 200) .attr("height", 100) .attr("id", "fobject") .style("border-color", d3.scale.category20c()) .append("xhtml:div") .style("font", "14px 'Helvetica Neue'") .html("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam."); var drag1 = d3.behavior.drag() .on("drag", function(d,i) { d3.select(this).attr("transform", function(d,i){ return "translate(" + [ d3.event.x,d3.event.y ] + ")" }) }); var drag2 = d3.behavior.drag() .on("drag", function(d,i) { d3.select(this) .attr("x", d3.event.x) .attr("y", d3.event.y); }); group.call(drag1); innerSvg.call(drag2); ``` I would very appreciate any explanation, naturally I prepared a working example here : http://jsfiddle.net/Y8y7V/

Original source