Reputation: 55283
The following code creates a background and a rectangle. The rectangle can be dragged:
var p = {
x: 0,
y: 0
}
var width = 400
var height = 400
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
svg.append('rect')
.attr('class', 'bg')
.attr('width', width)
.attr('height', height)
var drag = d3.behavior.drag()
.on('drag', dragmove)
svg.append('rect')
.attr('class', 'btn')
.attr('width', 100)
.attr('height', 50)
.attr('transform', 'translate(' + p.x + ',' + p.y + ')')
.call(drag)
function dragmove (d) {
var x = d3.event.x
var y = d3.event.y
d3.select(this)
.attr('transform', 'translate(' + x + ',' + y + ')')
}
The dragging event works, but there's an initial "jump" each time I drag the object (e.g the rectangle starts on the left of the cursor and then suddenly jumps to the right).
You can see it here: https://jsfiddle.net/alexcheninfo/5rnv7ww5/
What is causing it and how to prevent it (make the rectangle being dragged smoothly from the beginning)?
Upvotes: 2
Views: 651
Reputation: 121
For those who struggling this, my 50 cents. In d3 js v7 there is no event.dx or event.dy properties, instead you have to read event.movementX
and event.movementY
properties. Here is my working code (I only needed x position). The getTokenizedTransformAttributeValue
method is taken from here: https://www.it-swarm-es.com/es/javascript/sustitucion-de-d3.transform-en-d3-v4/825493251/
self=this;
const consty = 100; //example
let dragHandler = this.d3.drag()
.on("drag", function() {
const inputTrasformString = self.d3.select(this).attr("transform");
var transformObject = self.getTokenizedTransformAttributeValue(inputTrasformString);
x = event.movementX+parseInt(transformObject.translate[0])
self.d3.select(this)
.attr("transform", "translate("+x+","+consty+")");
}).on("start",function() {
//something
}).on("end", function() {
//something
});
dragHandler(svg.select(".myclass"));
Upvotes: 1
Reputation: 10035
you need to specify origin of the drag behaviour. By default the underlying data object is used. In you case - it's the p
object. So you would need to do this:
var drag = d3.behavior.drag()
.origin(function() { return p; })
.on('drag', dragmove)
and update it's x and y properties on every drag
function dragmove (d) {
// ...
// normally you would update d.x and d.y
p.x = d3.event.x;
p.y = d3.event.y;
// ...
}
See updated fiddle.
In d3 v4 this is called drag subject.
Upvotes: 1
Reputation: 32327
It should be this way:
//get the translate on the dragged rectangle
var translate = d3.transform(d3.select(this).attr("transform")).translate;
//to that add the mouse move deltax
x = d3.event.dx + translate[0],
y = d3.event.dy + translate[1];
working code here
when you do
var x = d3.event.x
var y = d3.event.y
d3.select(this)
.attr('transform', 'translate(' + x + ',' + y + ')')
It will translate the rectangle to the mouse position thus the jump.
Upvotes: 4