用文本d3js

时间:2017-11-07 04:52:44

标签: d3.js svg text newline bubble-chart

我有一个脚本,我可以通过以下方式制作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)属性,那么文本的对齐方式就不对了。见下图:

enter image description here

"状态"应该直接来到"爱荷华州"

更新了脚本:

 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");

我该怎么做才能使对齐正确或有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:2)

有不同的方法来解决这个问题。一个简单的方法是将<tspan>附加到<g>元素,将所有x属性设置为0,将text-anchor设置为middle

看看演示:

&#13;
&#13;
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;
&#13;
&#13;

PS:不要在for内使用each循环。这不是惯用 D3。而不是那样,只需使用输入选择(请参阅演示以了解如何操作)。