D3.js 在多系列折线图上有条件地显示标签

D3.js 在多系列折线图上有条件地显示标签,d3.js,charts,D3.js,Charts,在a的d3示例中,所有系列标签都显示在图形的最右侧。我感兴趣的是改变它们,使它们有条件地显示在图表的某些部分,或者根本不显示 因此,使用这个例子,如果我希望标签在每个系列上以最大值显示,并且与每个系列的颜色相同,也许类似,我该如何实现这一点?我想这和街区有关 city.append("text") .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; }) .attr("tran

在a的d3示例中,所有系列标签都显示在图形的最右侧。我感兴趣的是改变它们,使它们有条件地显示在图表的某些部分,或者根本不显示

因此,使用这个例子,如果我希望标签在每个系列上以最大值显示,并且与每个系列的颜色相同,也许类似,我该如何实现这一点?我想这和街区有关

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; });
但我不能解决这个问题。我尝试过使用IndexOf或MaxOf特性,但在这种情况下两者都无法工作。请注意,这可能会导致图表上出现一些重叠,不过我可以稍后再处理。任何人都可以获得额外的积分,他们可以展示如何添加带有指向最大值的线条的条件标签


谢谢:

如果不注意图表的可读性,一种解决方案可能是首先添加一个函数:

function find_max_date(max,values)
{
for (i=0;i<values.length;i++)
{
if (values[i].temperature==max)
{
return i;
break;
}
}
}
因此,基本上,这会将max和max_数据添加到数据对象max中,只需使用d3.max方法来查找最高温度,并通过循环每个城市的原始数据并返回数组中最高温度的位置来查找max_数据,用于访问相应的日期。添加颜色的方式与添加到线条的方式相同

编辑:不确定奖金问题,结果应该是什么样的?指向每个城市的最大值的线

edit2:奖金问题的可能解决方案,因为我很好奇它是否可行,但可能有更好的方法。我更改了代码的不同部分,因此可以删除函数find\u max\u date

在脚本的开头,我添加了一个全局变量

var offset=20;
作为变量控制标签之间的距离和边框。然后,在城市颜色域部分和比例域之间,我添加了以下代码:

for (i=0;i<cities.length;i++)
{
  cities[i].max=0;
  cities[i].label_off=0;
  for (j=0;j<cities[i].values.length;j++)
  {
    if (cities[i].values[j].temperature>cities[i].max) 
    {
      cities[i].max=cities[i].values[j].temperature;
      cities[i].max_date=cities[i].values[j].date;
    }
  }
}
最后是要添加标签和线条的零件。由于cities变量已包含所有必要的信息,您不需要使用其他数据,只需使用属性名称即可对其进行寻址:

city.append("text")
  .attr("transform", function(d) {return "translate(" + (x(d.max_date)+30+d.label_off) + "," + (offset+d.label_off) + ")"; })
  .attr("x", 3)
  .attr("dy", ".35em")
  .text(function(d) { return d.name; })
  .attr("fill",function(d) {return color(d.name);});

city.append("line")
  .attr("class","line_con")
  .attr("x1",function(d){return x(d.max_date);})
  .attr("y1",function(d){return y(d.max);})
  .attr("x2",function(d){return (x(d.max_date)+30+d.label_off);})
  .attr("y2",function(d){return (offset+d.label_off);})
  .attr("stroke",function(d) {return color(d.name);});
如您所见,变换只是将标签放在x刻度上最高温度日期的位置。然后它加上30,这是一个任意值,只是将它们稍微向右移动,这样它们就不会位于该值的正上方。d、 如果没有重叠,则label_off加0,在本例中,如果有重叠,则加20

在y刻度上,我将它们放置在图表顶部,使用偏移量在它们和边框之间留出一些空间。同样,如果有重叠,它们会向下移动一点

对于线,它只是连接标签的最大值和起点。它们使用不同的css类来允许相应的颜色:

.line_con {
  fill: none;
  stroke: none;
  stroke-width: 1.5px;

同样,可能有更好的方法来实现它,我不确定这是否适用于所有类型的数据,但它可能会让您知道如何处理它。

谢谢您的帮助,代码工作得非常完美。我说的第二点,是一个类似的例子。我想这可能会开始变得有点棘手,因为标签不会到处都是。嗯,这确实有点棘手,因为你需要避免标签重叠。如上所述,我在答案中编辑了一个可能的解决方案,但我不确定是否有更好的方法,或者这个标签是否完全合理。做得好!非常令人印象深刻,感谢您的帮助:
y.domain([
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; })+offset; })  
  ]);
city.append("text")
  .attr("transform", function(d) {return "translate(" + (x(d.max_date)+30+d.label_off) + "," + (offset+d.label_off) + ")"; })
  .attr("x", 3)
  .attr("dy", ".35em")
  .text(function(d) { return d.name; })
  .attr("fill",function(d) {return color(d.name);});

city.append("line")
  .attr("class","line_con")
  .attr("x1",function(d){return x(d.max_date);})
  .attr("y1",function(d){return y(d.max);})
  .attr("x2",function(d){return (x(d.max_date)+30+d.label_off);})
  .attr("y2",function(d){return (offset+d.label_off);})
  .attr("stroke",function(d) {return color(d.name);});
.line_con {
  fill: none;
  stroke: none;
  stroke-width: 1.5px;