我有一个脚本,我可以通过以下方式制作txts:
texts = svg.selectAll(null)
.data(data)
.enter()
.append('text')
.attr("text-anchor", "middle")
.text(function(d) {
return d.abbreviation;
})
.attr("pointer-events", "none")
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.attr("fill", "black");
texts.each(function(d) {
console.log(this.getComputedTextLength());
d.size = this.getComputedTextLength() / 2 ;
});
simulation.nodes(data).on("tick", function() {
circles.attr("cx", function(d) {
return d.x = Math.max(20, Math.min(width - 20, d.x));
})
.attr("cy", function(d) {
return d.y = Math.max(20, Math.min(height - 20, d.y));
})
texts.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
});
我在数据中使用属性缩写将文本放在气泡上,但我想用新行字符替换输入中的所有空格。
我尝试了以下链接提供的一些消息:How to linebreak an svg text in javascript? 但是所有文本都转到最左边的角落,或者如果我从中移除了.attr(" x",0)属性,那么文本的对齐方式就不对了。见下图:
"状态"应该直接来到"爱荷华州"
更新了脚本:
texts = svg.selectAll(null)
.data(data)
.enter()
.append('text')
.attr("text-anchor", "middle")
.each(function (d) {
var arr = d.abbreviation.split(" ");
for (i = 0; i < arr.length; i++) {
d3.select(this).append("tspan")
.text(arr[i])
.attr("dy", i ? "1.2em" : 0)
.attr("text-anchor", "middle")
.attr("class", "tspan" + i);
}
})
.attr("pointer-events", "none")
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.attr("fill", "black");
我该怎么做才能使对齐正确或有其他方法可以做到这一点?
答案 0 :(得分:2)
有不同的方法来解决这个问题。一个简单的方法是将<tspan>
附加到<g>
元素,将所有x
属性设置为0
,将text-anchor
设置为middle
。
看看演示:
var svg = d3.select("svg");
var data = [{
text: "some text"
}, {
text: "a longer text here"
}, {
text: "an even longer text here"
}, {
text: "short text"
}, {
text: "a long text"
}];
var texts = svg.selectAll(null)
.data(data)
.enter()
.append("g");
texts.append("text")
.attr("text-anchor", "middle")
.each(function(d) {
var arr = d.text.split(" ");
d3.select(this).selectAll(null)
.data(arr)
.enter()
.append("tspan")
.attr("text-anchor", "middle")
.attr("x", 0)
.attr("dy", function(d, i) {
return "1.2em"
})
.text(String)
})
var simulation = d3.forceSimulation(data)
.force("center", d3.forceCenter(200, 100))
.force("collide", d3.forceCollide(40))
.on("tick", tick);
function tick() {
texts.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
})
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="400" height="250"></svg>
&#13;
PS:不要在for
内使用each
循环。这不是惯用 D3。而不是那样,只需使用输入选择(请参阅演示以了解如何操作)。