如何使长标签的整个文本可见?

时间:2018-08-27 08:30:43

标签: javascript d3.js svg

我们有一个很长的文本需要包装,在D3.js中尝试时,整个文本都不可见。我尝试了多个选项来包装,但实际上无法使代码合适。

我看到tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight * dy + "em").text(word);行计算出了长度,但是我无法理解如何动态适应文本/使长文本可见。

我的TSV:

name    value
Committed 671 birthdays to it if there is a relevant source of information , it would be better to understand it and kids can be assigned relevant groups to particiate     .19
it should end up like this in the $_POST[] array (PHP format for easy   .19
just leave it there    .19
Ex is doing too well    .10
High school friends all dead now    .15
Discovered how to “like” things mentally    .27

我的代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.7/d3.min.js"></script>

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.bar {
  fill: steelblue;
}

.bar:hover {
  fill: brown;
}

.title {
  font: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.x.axis path {
  display: none;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var margin = {top: 80, right: 180, bottom: 80, left: 180},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1, .3);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(8, "%");

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.tsv("data.tsv", type, function(error, data) {
  x.domain(data.map(function(d) { return d.name; }));
  y.domain([0, d3.max(data, function(d) { return d.value; })]);

  svg.append("text")
      .attr("class", "title")
      .attr("x", x(data[0].name))
      .attr("y", -26)
      .text("Why Are We Leaving Facebook?");

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
    .selectAll(".tick text")
      .call(wrap, x.rangeBand());

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis);

  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.name); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); });
});

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

function type(d) {
  d.value = +d.value;
  return d;
}

</script>

这是结果:

enter image description here

1 个答案:

答案 0 :(得分:1)

首先,让我们进行适当的归属:名为wrap的函数是由Mike Bostock创建的,如您在此处看到的:https://bl.ocks.org/mbostock/7555321。您可能是从那里复制的,或者是从我们在互联网上找到的无数复制的文件中复制的。

话虽如此,这个答案将提出一个使用该功能的解决方案。当然,存在更好,性能更高的解决方案。

假设您的标签较长,如下所示:

"What would you think if I sang out of tune? 
Would you stand up and walk out on me?
Lend me your ears and I'll sing you a song 
And I'll try not to sing out of key"

在此提议的解决方案中,我们设置了一个计数器...

var counter = 0;

...,然后在wrap函数中,我们获得最大行数:

counter = lineNumber > counter ? lineNumber : counter;

利用这些信息,我们可以使用幻数(例如20)乘以最大行数并将轴向上推:

margin.bottom = 20 * counter;
height = 500 - margin.top - margin.bottom;
y.range([height, 0]);

下面是修改后的Bostock代码:https://bl.ocks.org/GerardoFurtado/91f656cf425cb630a4e5adf98d207f35/bcda7bdb86ffffdd84000a075811ea17d4f4218a

这里有重复项和不必要的步骤,您可以改进它们:此答案只是一个粗略的演示,向您展示了一种计算标签所需的必要空间的方法。

相关问题