换行文本功能不创建新行

Wrap text function not creating new lines

我有一个带标题的 d3 图表。标题是图表。但是,在小屏幕上,文本需要换行以免溢出。

然而,Bl.ocks 文本换行方法不会创建新行,而是为每个单词创建一个新的 tspan,然后将每个 text/tspan 一个一个地放在另一个上面

这是问题的 jsfiddle:jsfiddle here

这里是相关代码

var chartTitle = svg.append("text")
                .attr("y", -15 )
                .attr("text-anchor", "start")  
                .text("This is a very long chart title that should be wrapped!")
                .attr('class','chartTitle')
                      .call(wrap, width/2);



        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 = parseFloat(text.attr("dy")),
                  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);
                }
              }
            });
          }

CSS

.chartTitle{
  font-size:20px;
}

最初由 Mike Bostock(D3 创建者)为 wrapping labels 编写的 wrap 函数使用文本 dy 属性(由轴生成器自动创建)。也就是说,您的代码的问题在于该文本元素中没有 dy 属性。

您可以简单地调整函数或只设置零 dy 属性。这是使用后者的演示:

var svg = d3.select("body")
  .append("svg");

var chartTitle = svg.append("text")
  .attr("y", 20)
  .attr("dy", 0)//set the dy attribute
  .attr("text-anchor", "start")
  .text("This is a very long chart title that should be wrapped!")
  .attr('class', 'chartTitle')
  .call(wrap, 300 / 2);

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 = parseFloat(text.attr("dy")),
      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);
      }
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>