我正在使用D3js drag。单个元素被拖得很好。但我想拖动一组元素。如何做到这一点。这是Js Fiddle link上的内容:
function onDragDrop(dragHandler, dropHandler) {
var drag = d3.behavior.drag();
drag.on("drag", dragHandler)
.on("dragend", dropHandler);
return drag;
}
var g = d3.select("body").select("svg").append("g")
.data([{ x: 50, y: 50 }]);
g.append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("stroke", "red")
.attr("fill","transparent")
.attr("x", function (d) { return d.x; })
.attr("y", function (d) { return d.y; })
.call(onDragDrop(dragmove, dropHandler));
g.append("text")
.text("Any Text")
.attr("x", function (d) { return d.x; })
.attr("y", function (d) { return d.y; })
.call(onDragDrop(dragmove, dropHandler));
function dropHandler(d) {
// alert('dropped');
}
function dragmove(d) {
d3.select(this)
.attr("x", d.x = d3.event.x)
.attr("y", d.y = d3.event.y);
}
我想同时拖动rect和text。这是我tried,但没有运气。我想我错过了一些简单的事情。
答案 0 :(得分:23)
首先,< g> element不关心x
和y
属性(如:它们只是被忽略)。您可以改为使用transform="translate(x,y)"
。
其次,您需要检查您在dragmove处理程序中获得的元素是否实际上是< g>元素,而不是它的子元素。这是因为< g>元素本身没有实际的命中区域。他们的孩子会这样做,鼠标事件首先会传给孩子,然后冒泡到父母那里。您可以检查evt.target
和evt.currentTarget
以查看此操作。 target
是最初被点击的元素,currentTarget
是当前正在处理事件的事件目标(例如,如果事件冒泡,则为< g>元素)。
答案 1 :(得分:4)
对于d3 v4:
var drag_this = d3.drag().subject(this)
.on('start',function (d) {
if (d.x1){
d.x1 = d3.event.x - d.xt;
d.y1 = d3.event.y - d.yt;
}else{
d.x1 = d3.event.x;
d.y1 = d3.event.y;
}
})
.on('drag',function(d){
d3.select(this)
.attr("transform", "translate(" + (d3.event.x - d.x1) + "," + (d3.event.y - d.y1) + ")");
d.xt = d3.event.x - d.x1;
d.yt = d3.event.y - d.y1;
});
my_group.call(drag_this);
这假设您有绑定到该组的数据。