問題描述
Jsfiddle:http://jsfiddle.net/6NBy2/
代碼:
var in_editor_drag = d3.behavior.drag()
.origin(function() {
var g = this.parentNode;
return {x: d3.transform(g.getAttribute("transform")).translate[0],
y: d3.transform(g.getAttribute("transform")).translate[1]};
})
.on("drag", function(d,i) {
g = this.parentNode;
translate = d3.transform(g.getAttribute("transform")).translate;
x = d3.event.dx + translate[0],
y = d3.event.dy + translate[1];
d3.select(g).attr("transform", "translate(" + x + "," + y + ")");
d3.event.sourceEvent.stopPropagation();
});
svg = d3.select("svg");
d = {x: 20, y: 20 };
groups = svg
.append("g")
.attr("transform", "translate(20, 20)");
groups
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 100)
.style("fill", "green")
.call(in_editor_drag)
.style("opacity", 0.4);
我正在嘗試通過使用其中一個孩子作為句柄來拖動一個組.簡單地說,我想要做的是,當一個組的孩子被拖動時:
I'm trying to drag a group by using one of it's children as a handle. Simply, what i'm trying to do is, when a groups child is dragged:
- 獲取組的翻譯轉換
- 從 d3.event.dx、d3.event.dy 獲取拖動距離
- 對組的變換屬性應用差異
當拖動孩子時,組不會按預期移動.它移動的距離小于拖動的距離,并開始在這里和那里跳躍.
When child dragged, group does not move as expected. It moves less than the dragged distance, and it begins to jump here and there.
我在這里做錯了什么?
更新的 jsfiddle:http://jsfiddle.net/6NBy2/2/
Updated jsfiddle: http://jsfiddle.net/6NBy2/2/
我正在嘗試通過使用一個或多個孩子作為拖動手柄來拖動整個組.
I'm trying to drag the whole group by using one or more of it's children as dragging handles.
推薦答案
這是一個老問題,但沒有真正回答.我遇到了完全相同的問題,并且只想將組拖動一個子元素(不是 <g>
的所有子元素).問題是,d3.event.dx/y
是相對于 <g>
的位置計算的.一旦 <g>
被 .attr(transform", translate(x, y)")
移動,d3.event.dx/dy
被調整為新的(較小的)值.這會導致不平穩的運動,大約.光標速度的一半.我為此找到了兩種可能的解決方案:
This is an old question, but not really answered. I had exactly the same problem and wanted to drag the group by only one child (not all child elements of the <g>
).
The problem is, that the d3.event.dx/y
is calculated relatively to the position of the <g>
. And as soon as the <g>
is moved by .attr("transform", "translate(x, y)")
, the d3.event.dx/dy
is adjusted to the new (smaller) value. This results in a jerky movement with approx. the half of the speed of the cursor. I found two possible solutions for this:
首先(最后我采用了這種方法):
將拖動句柄 rect 直接附加到 svg 而不是 <g>
.所以它相對于 <svg>
而不是 <g>
定位.然后在 on drag 函數中同時移動(<rect>
和 <g>
).
Append the drag handle rect directly to the svg and not to the <g>
. So it is positioned relatively to the <svg>
and not to the <g>
. Then move both (the <rect>
and the <g>
) within the on drag function.
var svg = d3.select("svg");
var group = svg
.append("g").attr("id", "group")
.attr("transform", "translate(0, 0)");
group
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 100)
.style("fill", "green")
.style("opacity", 0.4);
group
.append("text")
.attr("x", 10)
.attr("y", 5)
.attr("dominant-baseline", "hanging")
.text("drag me");
handle = svg
.append("rect")
.data([{
// Position of the rectangle
x: 0,
y: 0
}])
.attr("class", "draghandle")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 20)
.style("fill", "blue")
.style("opacity", 0.4)
.attr("cursor", "move")
.call(d3.drag().on("drag", function (d) {
console.log("yep");
d.x += d3.event.dx;
d.y += d3.event.dy;
// Move handle rect
d3.select(this)
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
});
// Move Group
d3.select("#group").attr("transform", "translate(" + [d.x, d.y] + ")");
}));
<body>
<svg width="400" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
</body>
第二:
使用 d3.event.sourceEvent.path[0]
檢查拖動事件期間光標在哪個元素上,僅當句柄 <rect>
時才運行拖動功能代碼>被點擊.使用這種方法,所有元素都可以在一個 <g>
中進行分組(無需在組外添加額外的 <rect>
).這種方法的缺點是,如果鼠標向下移動光標到拖動手柄上,也會執行拖動.
Check on which element the cursor was during the drag event with d3.event.sourceEvent.path[0]
and run the drag function only if the handle <rect>
was clicked. With this approach, all elements can be grouped within one <g>
(no need for an additional <rect>
outside the group). The downside of this method is, that the drag is also executed, if the cursor is moved over the drag handle with mouse down.
var svg = d3.select("svg");
var group = svg
.append("g")
.data([{
// Position of the rectangle
x: 0,
y: 0
}])
.attr("id", "group")
.attr("transform", function (d) {
return "translate(" + d.x + ", " + d.y + ")"
})
.call(d3.drag().on("drag", function (d) {
if (d3.event.sourceEvent.target.classList.value === "draghandle") {
console.log("yep");
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function (d) {
return "translate(" + [d.x, d.y] + ")"
})
} else {
console.log("nope");
return;
}
}));
group
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 100)
.style("fill", "green")
.style("opacity", 0.4);
group
.append("text")
.attr("x", 10)
.attr("y", 5)
.attr("dominant-baseline", "hanging")
.text("drag me");
handle = group
.append("rect")
.attr("class", "draghandle")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 20)
.style("fill", "blue")
.style("opacity", 0.4)
.attr("cursor", "move");
<body>
<svg width="400" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
</body>
這篇關于D3js:使用其中一個子級拖動組的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!