正在处理Mike's example我试图找出如何将概念转移到分组元素。我可以单独创建启动拖动和单击,但在一起时我似乎无法单击来工作。下面是一个片段 - 这只是我使用过的众多方法之一。
const width = 400;
const height = 300;
const radius = 5;
const svg = d3.select("#chart").append('svg')
.attr('width', '400')
.attr('height', '400')
.style('border', 'solid 1px');
const circles = d3.range(20).map(i => ({
x: Math.random() * (width - radius * 2) + radius,
y: Math.random() * (height - radius * 2) + radius,
index: i
}));
const group = svg.selectAll("g").data(circles).enter()
.append("g")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
group.append("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", radius)
.attr("fill", d => d3.schemeCategory10[d.index % 10])
.on("click", clicked);
group.append("text")
.attr("x", d => d.x)
.attr("y", d => d.y)
.style("fill", 'white')
.text('a')
function clicked(event, d) {
if (event.defaultPrevented) return; // dragged
d3.select(this).transition()
.attr("fill", "black")
.attr("r", radius * 2)
.transition()
.attr("r", radius)
.attr("fill", d3.schemeCategory10[d.index % 10]);
}
function dragstarted() {
d3.select(this).attr("stroke", "black");
}
function dragged(event, d) {
d3.select(this).raise().attr("cx", d.x = event.x).attr("cy", d.y = event.y);
}
function dragended() {
d3.select(this).attr("stroke", null);
}
<script src="https://d3js.org/d3.v6.js"></script>
<div id="chart"></div>
最佳答案
关键问题是您使用 cx
、cy
属性定位每个 g
,并在拖动时更新这些属性。 g
元素无法通过 cx
或 cy
定位,因此最初设置这些元素并在拖动时更新它们将不会导致任何变化。
您需要使用翻译来定位 g
元素:
.attr("transform", d=> "translate("+[d.x,d.y]+")" )
此外,您现在不需要定位圆圈和文本 - 或者每个 x 和 y 坐标将应用两次 - 一次应用于 g
,一次应用于子元素。
现在您只需要在每次拖动时更新翻译,例如:
function drag(event,d) {
d.x = event.x;
d.y = event.y;
d3.select(this).raise().attr("transform", d=> "translate("+[d.x,d.y]+")" )
}
这应该给你类似的东西:
const width = 400;
const height = 300;
const radius = 5;
const svg = d3.select("#chart").append('svg')
.attr('width', '400')
.attr('height', '400')
.style('border', 'solid 1px');
const circles = d3.range(20).map(i => ({
x: Math.random() * (width - radius * 2) + radius,
y: Math.random() * (height - radius * 2) + radius,
index: i
}));
const group = svg.selectAll("g").data(circles).enter()
.append("g")
.attr("transform", d=> "translate("+[d.x,d.y]+")" )
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
group.append("circle")
.attr("r", radius)
.attr("fill", d => d3.schemeCategory10[d.index % 10])
.on("click", clicked);
group.append("text")
.style("fill", 'white')
.text('a')
function clicked(event, d) {
if (event.defaultPrevented) return; // dragged
d3.select(this).transition()
.attr("fill", "black")
.attr("r", radius * 2)
.transition()
.attr("r", radius)
.attr("fill", d3.schemeCategory10[d.index % 10]);
}
function dragstarted() {
d3.select(this).attr("stroke", "black");
}
function dragged(event, d) {
d.x = event.x;
d.y = event.y;
d3.select(this).raise().attr("transform", d=> "translate("+[d.x,d.y]+")" )
}
function dragended() {
d3.select(this).attr("stroke", null);
}
<script src="https://d3js.org/d3.v6.js"></script>
<div id="chart"></div>
关于d3.js - D3 在 v6 中拖动并单击分组对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64397454/