javascript - D3js: Kéo một nhóm bằng cách sử dụng một trong các phần tử con của nó
Jsfiddle: http://jsfiddle.net/6NBy2/
Mã :
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);
Tôi đang cố gắng kéo một nhóm bằng cách sử dụng một trong các phần tử con của nó như một tay cầm. Nói đơn giản, những gì tôi đang cố gắng làm là, khi một phần tử con của nhóm bị kéo:
- Lấy biến đổi dịch của nhóm
- Lấy khoảng cách kéo từ d3.event.dx, d3.event.dy
- Áp dụng sự khác biệt vào thuộc tính biến đổi của nhóm
Khi trẻ bị kéo, nhóm không di chuyển như mong đợi. Nó di chuyển ít hơn khoảng cách bị kéo, và bắt đầu nhảy đây đó.
Tôi đang làm sai điều gì ở đây?
Chỉnh sửa:
JsFiddle đã cập nhật: http://jsfiddle.net/6NBy2/2/
Tôi đang cố gắng kéo toàn bộ nhóm bằng cách sử dụng một hoặc nhiều đứa con của nó như các tay cầm kéo.
Câu trả lời #1
Đây là một câu hỏi cũ, nhưng thực sự chưa được trả lời. Tôi cũng gặp đúng vấn đề này và muốn kéo nhóm chỉ bằng một phần tử con (không phải tất cả các phần tử con của <g>). Vấn đề là, d3.event.dx/y được tính toán tương đối so với vị trí của <g>. Và ngay khi <g> được di chuyển bằng .attr(“transform ”, “translate(x, y) ”), d3.event.dx/dy được điều chỉnh về giá trị mới (nhỏ hơn). Điều này dẫn đến chuyển động giật cục với tốc độ khoảng một nửa so với con trỏ. Tôi đã tìm thấy hai giải pháp khả thi cho điều này:
Đầu tiên (cuối cùng tôi đã đi đến phương pháp này):
Đính trực tiếp hình chữ nhật tay kéo vào svg chứ không phải vào <g>. Như vậy nó sẽ được định vị tương đối với <svg> chứ không phải với <g>. Sau đó di chuyển cả hai (cả <rect> và <g>) trong hàm on drag.
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>Thứ hai:
Kiểm tra xem con trỏ đang ở phần tử nào trong sự kiện kéo với d3.event.sourceEvent.path[0] và chỉ chạy hàm kéo nếu tay cầm <rect> được nhấp. Với cách tiếp cận này, tất cả các phần tử có thể được nhóm trong một <g> (không cần thêm <rect> bên ngoài nhóm). Nhược điểm của phương pháp này là kéo cũng được thực hiện nếu con trỏ di chuyển qua tay cầm kéo khi nhấn chuột.
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>Câu trả lời số 2
Sử dụng drag.container() để thiết lập bộ truy cập container.
Xem tài liệu D3.
