我是使用d3.js的新手。我正在尝试在svg组中附加多个文本元素。这样,我希望能够拖动多组文本。
举个例子:
export function testNode (config = {}) {
let { svg, rectX, rectY, text1, text2 } = config
var data = [{ x: rectX, y:rectY, label: text1, label2: text2, labelX: rectX + 100, labelY: rectY + 200, labelX2: rectX + 300, labelY2: rectY + 300 }]
var group = svg.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",
"translate(" + 0 + "," + 0 + ")")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
group.append("text")
.data(data)
.attr("x", (d) => { return d.labelX })
.attr("y", (d) => { return d.labelY })
.attr("font-size", "1em")
.attr("color", "black")
.text((d) => { return d.label });
group.append("text")
.data(data)
.attr("x", (d) => { return d.labelX2 })
.attr("y", (d) => { return d.labelY2 })
.attr("font-size", ".75em")
.attr("color", "black")
.attr("class", "label")
.text((d) => { return d.metricValue_01 });
function dragStarted() {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this).select("text")
.attr("x", d.labelX = d3.event.x + 10)
.attr("y", d.labelY = d3.event.y + 20);
d3.select(this).select("text")
.attr("x", d.labelX2 = d3.event.x + 10)
.attr("y", d.labelY2 = d3.event.y + 20);
function dragended() {
d3.select(this).classed("active", false);
}
如果我使用selectAll方法,则文本会聚在一起。因此,我想知道是否可以根据我给它的坐标(拖动时)将文本组拖动到适当的位置。无论如何,请让我知道是否需要提供更多信息。谢谢
答案 0 :(得分:0)
如果您要选择第二个标签,但又不想同时使用selectAll
,则可以在添加时提供标签类,而在拖动时选择标签类:
d3.select(this).select(".bigLabel")
.attr("x", d.labelX = d3.event.x + 10)
.attr("y", d.labelY = d3.event.y + 20);
d3.select(this).select(".smallLabel")
.attr("x", d.labelX2 = d3.event.x + 10)
.attr("y", d.labelY2 = d3.event.y + 20);
当然,除非您指定偏移量,否则这将为两个标签设置相同的坐标,
var data = [
{ x: 100, x2: 100, y: 100, y2: 120, label: "label1", value: "17%" },
{ x: 300, x2: 300, y: 200, y2: 220, label: "label2", value: "83%" },
{ x: 100, x2: 100, y: 200, y2: 220, label: "label3", value: "11%" },
{ x: 300, x2: 300, y: 100, y2: 120, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.call(d3.drag()
.on("drag",drag));
labels.append("text")
.attr("font-size", "1em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y;})
.text(function(d) { return d.label; })
.attr("class","label1");
labels.append("text")
.attr("font-size", ".75em")
.attr("x", function(d) { return d.x2;})
.attr("y", function(d) { return d.y2;})
.text(function(d) { return d.value; })
.attr("class","label2");
function drag(d) {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.select(".label1")
.attr("x", function(d) { return d.x = x; })
.attr("y", function(d) { return d.y = y; })
d3.select(this)
.select(".label2")
.attr("x", function(d) { return d.x2 = x; })
.attr("y", function(d) { return d.y2 = y + 20; })
}
text {
text-anchor:middle;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>
我不会深入探讨替代方法,但是它将拖动应用于g
,同时放置两个文本标签。这样可以比上述方法更轻松地处理同级标签之间的不规则间距:
var data = [
{ x: 100, y: 100, label: "label1", value: "17%" },
{ x: 300, y: 200, label: "label2", value: "83%" },
{ x: 100, y: 200, label: "label3", value: "11%" },
{ x: 300, y: 100, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",function(d) {
return "translate("+[d.x,d.y]+")";
})
.call(d3.drag().on("drag", drag));
labels.append("text")
.attr("font-size", "1em")
.text(function(d) { return d.label; });
labels.append("text")
.attr("font-size", ".75em")
.text(function(d) { return d.value; })
.attr("dy", "1em")
function drag(d) {
d3.select(this)
.attr("transform","translate("+[d.x=d3.event.x,d.y=d3.event.y]+")");
}
text {
text-anchor: middle;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>
此外,无需使用append("text").data(data)
,这没有做任何事情-您的数据已绑定到新添加的元素
最后,如果您在设置属性时使用任何提供的函数的第二个参数来设置属性,那么可以使用selectAll()来完成此工作:(d,i)=>...
i是元素的索引,因此如果您的兄弟姐妹标签是有规律地隔开的,您可以使用类似
var data = [
{ x: 100, y: 100, label: "label1", value: "17%" },
{ x: 300, y: 200, label: "label2", value: "83%" },
{ x: 100, y: 200, label: "label3", value: "11%" },
{ x: 300, y: 100, label: "label4", value: "96%" }
];
var svg = d3.select("svg");
var labels = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.call(d3.drag()
.on("drag",drag));
labels.append("text")
.attr("font-size", "1em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y;})
.text(function(d) { return d.label; })
labels.append("text")
.attr("font-size", ".75em")
.attr("x", function(d) { return d.x;})
.attr("y", function(d) { return d.y + 20;})
.text(function(d) { return d.value; })
function drag(d) {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.selectAll("text")
.attr("x", function(d) { return d.x = x; })
.attr("y", function(d,i) { d.y = y;
return d.y + i * 20;
})
}
text {
text-anchor:middle;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="400"></svg>