带有文本锚点的 D3 文本换行:中间
D3 text wrap with text-anchor: middle
在 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>
从 docs for text-anchor,middle
将产生以下结果:
The rendered characters are aligned such that the middle of the text string is at the current text position.
在您的情况下,当您将文本分解为 tspan
时,x
等于 0
-- 当前文本位置 将是 svg 的开始(即在点 0)。此外,应用于 text
元素的 x:50
根本无关紧要。
一种方法是将中心值即 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);
}
}
});
}
#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>
另一种方法是按以下方式将 'transform' 属性 应用于文本:
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);
}
}
});
}
#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>
在上述两种方法中,我都没有使用 y 中心值,即 100,而是根据文本高度计算中点使用 getBoundingClientRect()
函数。
var height = plot.select('text').node().getBoundingClientRect().height;
plot.select('text').attr('y', 100-height/2);
希望这对您有所帮助。 :)
在 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>
从 docs for text-anchor,middle
将产生以下结果:
The rendered characters are aligned such that the middle of the text string is at the current text position.
在您的情况下,当您将文本分解为 tspan
时,x
等于 0
-- 当前文本位置 将是 svg 的开始(即在点 0)。此外,应用于 text
元素的 x:50
根本无关紧要。
一种方法是将中心值即 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); } } }); }
#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>
另一种方法是按以下方式将 'transform' 属性 应用于文本:
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); } } }); }
#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>
在上述两种方法中,我都没有使用 y 中心值,即 100,而是根据文本高度计算中点使用 getBoundingClientRect()
函数。
var height = plot.select('text').node().getBoundingClientRect().height;
plot.select('text').attr('y', 100-height/2);
希望这对您有所帮助。 :)