4

我根据此处找到的示例创建了一个折线图:

http://bl.ocks.org/mbostock/3884955

但是,对于我的数据,线标签(城市)最终会重叠,因为不同线的 y 轴上的最终值经常靠近。我知道我需要比较每行的最后一个值,并在值相差 12 个单位或更少时向上或向下移动标签。我的想法是查看这段代码编写的文本标签

city.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," +  y(d.value.temperature) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });

如果 y(d.value.temperature) 值相差 12 或更小,则将这些值分开,直到它们之间至少有 12 个单位。关于如何完成这项工作的任何想法?这是我的第一个 d3 项目,语法仍然很适合我!

4

2 回答 2

2

一次传递所有标签可能会更好——这也更符合一般 d3 的想法。然后你可以有这样的代码:

svg.selectAll("text.label").data(data)
   .enter()
   .append("text")
   .attr("transform", function(d, i) {
       var currenty = y(d.value.temperature);
       if(i > 0) {
           var previousy = y(data[i-1].value.temperature),
           if(currenty - previousy < 12) { currenty = previousy + 12; }
       }
       return "translate(" + x(d.value.date) + "," +  currenty + ")";
   })
   .attr("x", 3)
   .attr("dy", ".35em")
   .text(function(d) { return d.name; });

这没有考虑到前一个标签可能已被移动的事实。您可以显式获取前一个标签的位置,并根据该位置移动当前标签。代码几乎相同,只是您需要保存对当前元素 ( this) 的引用,以便以后可以访问它。

所有这些都不会阻止标签与它们最终标记的线条相距甚远。如果您需要移动每个标签,最后一个标签会很远。更好的做法可能是单独创建一个图例,您可以根据需要在其中间隔标签和线条。

于 2013-04-01T18:13:08.480 回答
2

考虑使用 D3 强制布局来放置标签。在此处查看示例:https ://bl.ocks.org/wdickerson/bd654e61f536dcef3736f41e0ad87786

假设您有一个data包含具有value属性和比例的对象的数组y

// Create some nodes
const labels = data.map(d => {
  return {
    fx: 0,
    targetY: y(d.value)
  };
});

// Set up the force simulation
const force = d3.forceSimulation()
  .nodes(labels)
  .force('collide', d3.forceCollide(10))
  .force('y', d3.forceY(d => d.targetY).strength(1))    
  .stop();

// Execute thte simulation
for (let i = 0; i < 300; i++) force.tick();

// Assign values to the appropriate marker
labels.sort((a, b) => a.y - b.y);
data.sort((a, b) => b.value - a.value);
data.forEach((d, i) => d.y = labels[i].y);

现在您的data数组将有一个y表示其最佳位置的属性。

示例使用 D3 4.0,在此处阅读更多内容:https ://github.com/d3/d3-force

于 2017-05-16T14:28:19.480 回答