Is there a way to click anywhere in an svg and have an element snap to that location and simultaneously begin dragging?
The closest I've gotten is in the code below. Dragging the circle works and clicking elsewhere will make the circle move to that location, but I can't figure out how to start the drag without releasing the mouse and directly clicking the circle.
More generally, how can I start the drag behavior without directly interacting with the element being dragged?
/
var width = 200,
height = 200,
radius = 10;
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function(){
d3.event.sourceEvent.stopPropagation()
})
.on("drag", dragmove);
var svg = d3.select("body")
.data([{x: 100, y : 100}])
.append('svg')
.attr("height", 200)
.attr("widht", 200)
.on("mousedown", function(){
circle.each(dragmove)
});
var circle = svg.append("circle")
.attr("r", radius)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.call(drag);
function dragmove(d) {
d3.select(this)
.attr("cx", d.x = Math.max(radius, Math.min(width - radius, d3.event.x)))
.attr("cy", d.y = Math.max(radius, Math.min(height - radius, d3.event.y)));
}
Is there a way to click anywhere in an svg and have an element snap to that location and simultaneously begin dragging?
The closest I've gotten is in the code below. Dragging the circle works and clicking elsewhere will make the circle move to that location, but I can't figure out how to start the drag without releasing the mouse and directly clicking the circle.
More generally, how can I start the drag behavior without directly interacting with the element being dragged?
http://jsfiddle/Hj44M/1/
var width = 200,
height = 200,
radius = 10;
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function(){
d3.event.sourceEvent.stopPropagation()
})
.on("drag", dragmove);
var svg = d3.select("body")
.data([{x: 100, y : 100}])
.append('svg')
.attr("height", 200)
.attr("widht", 200)
.on("mousedown", function(){
circle.each(dragmove)
});
var circle = svg.append("circle")
.attr("r", radius)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.call(drag);
function dragmove(d) {
d3.select(this)
.attr("cx", d.x = Math.max(radius, Math.min(width - radius, d3.event.x)))
.attr("cy", d.y = Math.max(radius, Math.min(height - radius, d3.event.y)));
}
Share
Improve this question
edited May 25, 2014 at 8:03
sfletche
49.9k31 gold badges109 silver badges120 bronze badges
asked May 25, 2014 at 7:13
procterwprocterw
1311 silver badge9 bronze badges
1
- It sounds like you would want a click handler on your SVG that moves the circle to the location of the click. – Lars Kotthoff Commented May 25, 2014 at 10:49
1 Answer
Reset to default 5UPDATE
I've solved this issue with a sort of brute-force solution: I removed the drag behavior and just added mousedown, mousemove, and mouseup handlers to the svg canvas. This is the functionality I want but I'd still prefer to use d3's drag behavior. If anyone has a more elegant solution do let me know.
http://jsfiddle/Hj44M/5/
var width = 200,
height = 200,
radius = 10;
var isDown = false;
var svg = d3.select("body")
.data([{x: 100, y : 100}])
.append('svg')
.attr("height", 200)
.attr("width", 200)
.on("mousedown", function(){
isDown = true;
var coordinates = d3.mouse(this);
circle.each(function(d){
circle.attr("cx", d.x = coordinates[0])
circle.attr("cy", d.y = coordinates[1])
})
})
.on("mousemove", function(){
if(isDown) {
var coordinates = d3.mouse(this);
circle.each(function(d){
circle.attr("cx", d.x = coordinates[0])
circle.attr("cy", d.y = coordinates[1])
})
}
})
.on("mouseup", function(){
isDown = false;
});
var circle = svg.append("circle")
.attr("r", radius)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });