I'm implementing the drag example from https://observablehq.com/@d3/circle-dragging-i using d3v7.
When I try the code it works correctly for the first drag, however from the start of the second drag, the position resets/jumps to the original one provided in the join data.
It appears that the event position is influenced by the data. I have confirmed this behavior using logs that tell me the starting position and the event and comparing it to the one given to me by the browser inspector.
After much toiling I found out that the issue here is in the way that the data has it's variables called x
and y
:
var circles = d3.range(20).map(i => ({
x: Math.random() * (width - radius * 2) + radius,
y: Math.random() * (height - radius * 2) + radius,
}));
By changing the data:
var circles = d3.range(20).map(i => ({
posx: Math.random() * (width - radius * 2) + radius,
posy: Math.random() * (height - radius * 2) + radius,
}));
I am able to drag the circles as intended.
Interestingly, if I update the position of the variable circles, this updated data is not reflected in the jump behaviour, by that I mean that the jump will happen to the initial value.
Should the name of the data influence the initial position of the items?
Why does the drag position resets after the first drag? (I tried changing the x
, y
properties alongside cx
and cy
, but the reset still happens).
Full code with problematic behaviour:
<!DOCTYPE html>
<html lang="en">
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
radius = 32;
height = 600;
width = 800;
function dragStart(event,d){
d3.select(this)
.style("stroke", "black")
console.log("Start",[event.x,event.y])
var current = d3.select(this);
console.log([current.attr("cx"),current.attr("cy")]);
console.log(current.attr("translate"));
}
function dragging(event,d){
var current = d3.select(this);
current
.attr('cx', event.x)
.attr('cy', event.y);
}
function dragEnd(event,d){
d3.select(this)
.style("stroke", "")
console.log("End",[event.x,event.y])
var current = d3.select(this);
console.log(d3.select(this));
}
drag = d3.drag()
.on("start", dragStart)
.on("drag", dragging)
.on("end", dragEnd);
var svg = d3.select("body")
.append("svg")
.attr("viewBox", [0, 0, width, height])
.attr("stroke-width", 2);
var circles = d3.range(20).map(i => ({
x: Math.random() * (width - radius * 2) + radius,
y: Math.random() * (height - radius * 2) + radius,
}));
console.log(circles);
console.log(drag);
svg.selectAll("circle")
.data(circles)
.join("circle")
.attr("cx", (d)=>d.x)
.attr("cy", (d)=>d.y)
.attr("r", radius)
.attr("fill", (d, i) => d3.schemeCategory10[i % 10])
.on("click",e => console.log(d3.pointer(e)))
.call(drag);
</script>
</body>
</html>