问题描述
在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.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>
解决方法
关键问题是您要为每个g
设置cx
,cy
属性,并在拖动时更新它们。 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.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.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.y]+")" )
}
function dragended() {
d3.select(this).attr("stroke",null);
}
<script src="https://d3js.org/d3.v6.js"></script>
<div id="chart"></div>