在D3中,我想要包含具有中间文本锚点的文本。我看了this example from Mike Bostok,但我无法绕过设置。
我希望看到文本位于红色框的中心(水平和垂直)。
var plot = d3.select(container)
.insert("svg")
.attr('width', 100)
.attr('height', 200);
plot.append("text")
.attr("x", 50)
.attr("y", 100)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "alphabetic")
.text("The brown fox jumps!")
.call(wrap, 100);
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = 1,
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
鉴于来自Shashank的指针,我现在能够使用translate方法将文本置于中心位置。只是设置文本的y似乎没有改变任何东西。我还添加了一个yTrack变量,以便能够继续在包装文本下面绘图。
let yTrack = 100,
plot = d3.select(container)
.insert("svg")
.attr('width', 100)
.attr('height', 200);
plot.append("text")
.attr("x", 50)
.attr("y", yTrack)
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.text("The quick brown fox jumps over the lazy dog.")
.call(wrap, 100);
let height = parseInt(plot.select('text').node().getBoundingClientRect().height);
plot.select("text").attr('transform', 'translate(0, ' + (-height / 2) + ')');
//plot.select("text").attr('y', 0);
yTrack += (parseInt(height / 2) + 10);
plot.append('rect')
.attr("x", 0)
.attr("y", yTrack)
.attr("width", 100)
.attr("height", 10)
.style('fill', '#999');
function wrap(text, width) {
text.each(function() {
let text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 1.1,
tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}

#container {
height: 200px;
width: 100px;
border: 1px solid red;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container"></div>
&#13;
答案 0 :(得分:3)
从{{3>} for text-anchor ,middle
将产生以下结果:
对齐渲染的字符,使文本字符串的中间位于当前文本位置。
在您的情况下,当您将文字分解为tspan
且x
等于0
时,当前文字位置将是svg的开始(即在0点)。此外,应用于x:50
元素的text
根本不重要。
一种方法是将中心值(即50)应用于tspan
s:
tspan.attr("x", 50)
这是一个代码片段:
var plot = d3.select(container)
.insert("svg")
.attr('width', 100)
.attr('height', 200);
plot.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "alphabetic")
.text("The brown fox jumps!")
.call(wrap, 100);
var height = plot.select('text').node().getBoundingClientRect().height;
plot.select('text').attr('y', 100-height/2);
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 0.1, // ems
y = text.attr("y"),
dy = 1,
tspan = text.text(null).append("tspan").attr("x", 50).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 50).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
&#13;
#container {
height: 200px;
width: 100px;
border: 1px solid red;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container"></div>
&#13;
另一种方法是应用&#39;转换&#39;属性如下:
plot.select('text').attr('transform', 'translate(50, ' + (100-height/2)+')');
以下是使用此方法的代码段:
var plot = d3.select(container)
.insert("svg")
.attr('width', 100)
.attr('height', 200);
plot.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "alphabetic")
.text("The brown fox jumps!")
.call(wrap, 100);
var height = plot.select('text').node().getBoundingClientRect().height;
plot.select('text').attr('transform', 'translate(50, ' + (100-height/2)+')');
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 0.1, // ems
y = text.attr("y"),
dy = 1,
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
&#13;
#container {
height: 200px;
width: 100px;
border: 1px solid red;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container"></div>
&#13;
在上述两种方法中,我都没有使用y中心值,即 100 ,而是根据文本高度计算中点,以及使用getBoundingClientRect()
功能。
var height = plot.select('text').node().getBoundingClientRect().height;
plot.select('text').attr('y', 100-height/2);
希望这会有所帮助。 :)