d3.js 添加图例到多条线系列图表中。

10

如何向多线系列图表添加图例?我尝试了但未能显示出任何图例。

这里的代码块:

http://bl.ocks.org/3884955

当各个系列汇聚到同一点(如零)时,存在缺陷。所有标签将重叠在彼此之上。与其使用这些标签,传统的图例会更实用。

我尝试添加以下内容

var legend = svg.append("g")
.attr("class", "legend")
.attr("height", 100)
.attr("width", 100)
.attr('transform', 'translate(-20,50)');    

legend.selectAll('rect')
  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  .append("rect")
  .attr("x", width)
  .attr("y", function(d, i){ return i *  20;})
  .attr("width", 10)
  .attr("height", 10)
  .style("fill", function(d) { 
    return color.domain(d3.keys(d[0]).filter(function(key) { return key !== "day"; }));
  });

legend.selectAll('text')
  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  .append("text")
  .attr("x", width)
  .attr("y", function(d, i){ return i *  20 + 9;})
  .text(function(d) {
  return d.name;
  });
到了代码的末尾,键名(d.name)与我的数据格式匹配,但没有显示。有一次它显示在图表右侧的所有黑框,这意味着我接近成功了,但我还缺少一些重要的东西。
感谢任何见解。
2个回答

13

这里是你的代码的修正版本。

    var legend = svg.selectAll('g')
        .data(cities)
        .enter()
      .append('g')
        .attr('class', 'legend');

    legend.append('rect')
        .attr('x', width - 20)
        .attr('y', function(d, i){ return i *  20;})
        .attr('width', 10)
        .attr('height', 10)
        .style('fill', function(d) { 
          return color(d.name);
        });

    legend.append('text')
        .attr('x', width - 8)
        .attr('y', function(d, i){ return (i *  20) + 9;})
        .text(function(d){ return d.name; });
你需要使用enter(),但是enter()exit()方法不能datum()一起使用。引用自d3 wiki

selection.datum([value])

获取或设置每个选定元素的绑定数据。与selection.data方法不同,该方法不会计算连接(因此不会计算enter和exit选择)。


1
我在代码里加了一个点,现在你的代码对我来说可以正常工作了。变量 legend = svg.selectAll('.g')。 - theUser

0

看起来你在 .datum() 函数调用后缺少了 .enter()。

legend.selectAll('rect')

  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })

  .enter() // <======

  .append("rect")

  .attr("x", width)

  .attr("y", function(d, i){ return i *  20;})

  .attr("width", 10)

  .attr("height", 10)

  .style("fill", function(d) { 

    return color.domain(d3.keys(d[0]).filter(function(key) { return key !== "day"; }));

在添加“rect”之前,您必须使用enter()函数,请参见链接以获取详细说明点击这里


嗯,我发现这个逻辑有一些不一致之处,在示例图中,city变量在某些地方以.append("text")开始,然后是.datum(...),之后没有enter(),只是修改属性。而当我添加了enter()时,控制台显示对象没有enter()并报错。 - CQM
我可能错了,但我认为混淆的原因在于(如果我理解正确的话).datum()将值添加/更改到选择中现有的元素中。在您的代码中,当您声明“legend.selectAll('rect')”时,没有任何元素存在,要创建初始连接,您需要使用“.data(data).enter()”来创建新的“rect”元素。 - Alex_B
这是一个关于.data和.datum的问题的好答案:https://dev59.com/_2Ys5IYBdhLWcg3wDfl5 - Alex_B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接