Reputation: 511
I've appended an svg container inside a g element and then appended a rect. I can transform and translate the g element into position which also positions the svg and rectangle. The g element has a drag function but event.x for the drag always starts at 0 and then goes negative for drag to the left. How can I access .attr("x") for the g element? I need to find the screen position for the start of the g element to pass onto another function.
I add the g
elements as follows:
.join(function (group) {
var gEnter = group.append("g")
.attr("class", "rectangles")
.append("svg")
.attr("class", "container");
...
I position my g
elements and call the drag function like so:
svg.selectAll(".rectangles")
.attr("transform", function (d, i) {return "translate(" + d.x + "," + d.y + ")";})
...
.call(d3.drag().on("dragged", dragged)...);
Then I call the drag function on those g
elements and update that position in the drag function:
function dragged(event, d) {
d3.select(this).attr("transform", function (d, i) {return "translate(" + event.x + "," + event.y + ")";})
}
Upvotes: 1
Views: 396
Reputation: 38171
You are not updating your datum to reflect the new position. You need to update d.x and d.y:
function dragged(event, d) {
d.x = event.x; d.y = event.y; // update the datum.
d3.select(this).attr("transform", function (d, i) {return "translate(" + event.x + "," + event.y + ")";})
}
By default, the drag subject is the datum, using d.x
and d.y
to represent the x,y coordinate of the thing being dragged. The drag is relative to this - one pixel right is d.x+1
regardless of where the mousedown event was. So if you never update the datum, each new drag event will be relative to the initial starting point.
If you want the screen position after the drag, that's d.x
and d.y
, if you update the datum throughout the drag:
var svg = d3.select("svg");
var circle = svg.append("circle")
.datum({x: 100, y:100})
.attr("r", 10)
.attr("transform", function(d) { return "translate("+[d.x,d.y]+")"; })
.call(d3.drag().on("drag", function(event,d) {
d.x = event.x, d.y = event.y;
d3.select(this).attr("transform", function(d) { return "translate("+[d.x,d.y]+")"; });
console.log("x: ", d.x);
}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg><svg>
Note that d
doesn't necessarily hold the screen position, but the position in SVG coordinate space
This may also be useful.
Upvotes: 1