最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - d3js Create legend for bar chart - Stack Overflow

programmeradmin1浏览0评论

I'm having a couple of issues with my bar chart. The current issue is trying to create a legend. The legend should read Global and Local (blue & green). Currently the legend generates 5 boxes - 2 of them are colored. I assume it's going through my dataset and generating boxes for each set of columns. I do not want this.

After I get the legend formatted, I want to be able to have it interactive. So if they only want to see global, then they unselect local, and the chart updates dynamically. I know I'll need to adjust it and create a function to update data, domain, etc.

But before beginning down that road, I want to get the legend populating properly. But I would appreciate if the legend solution would lead down this road.

I have a working Fiddle you can play around with.

Data Sources

var colors =    {0: ["Local", "#377EB8"],
             1: ["Global", "#4DAF4A"]};

var dataset = [
            {"keyword": "payday loans", "global": 1400000, "local": 673000, "cpc": "14.11"},
            {"keyword": "title loans", "global": 165000, "local": 160000, "cpc": "12.53" },
            {"keyword": "personal loans", "global": 550000, "local": 301000, "cpc": "6.14"},
            {"keyword": "online personal loans", "global": 15400, "local": 12900, "cpc": "5.84"},
            {"keyword": "online title loans", "global": 111600, "local": 11500, "cpc": "11.74"}
        ];

Label Code

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


legend.selectAll('rect')
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", w - 65)
    .attr("y", function(d, i) {
        return i * 20;
    })
    .attr("width", 10)
    .attr("height", 10)
    .style("fill", function(d) {
        var color = colors[dataset.indexOf(d)][1];
        return color;
    });

legend.selectAll('text')
    .data(dataset)
    .enter()
    .append("text")
    .attr("x", w - 52)
    .attr("y", function(d, i) {
        return i * 20 + 9;
    })
    .text(function(d) {
        var text = colors[dataset.indexOf(d)][0];
        return text;
    });

I know my Colors array/object probably isn't the most efficient way. So I'm open to adjusting that if it helps with the solution. Also, I would prefer that it is a Horizontal list instead of vertical.

I'm having a couple of issues with my bar chart. The current issue is trying to create a legend. The legend should read Global and Local (blue & green). Currently the legend generates 5 boxes - 2 of them are colored. I assume it's going through my dataset and generating boxes for each set of columns. I do not want this.

After I get the legend formatted, I want to be able to have it interactive. So if they only want to see global, then they unselect local, and the chart updates dynamically. I know I'll need to adjust it and create a function to update data, domain, etc.

But before beginning down that road, I want to get the legend populating properly. But I would appreciate if the legend solution would lead down this road.

I have a working Fiddle you can play around with.

Data Sources

var colors =    {0: ["Local", "#377EB8"],
             1: ["Global", "#4DAF4A"]};

var dataset = [
            {"keyword": "payday loans", "global": 1400000, "local": 673000, "cpc": "14.11"},
            {"keyword": "title loans", "global": 165000, "local": 160000, "cpc": "12.53" },
            {"keyword": "personal loans", "global": 550000, "local": 301000, "cpc": "6.14"},
            {"keyword": "online personal loans", "global": 15400, "local": 12900, "cpc": "5.84"},
            {"keyword": "online title loans", "global": 111600, "local": 11500, "cpc": "11.74"}
        ];

Label Code

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


legend.selectAll('rect')
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", w - 65)
    .attr("y", function(d, i) {
        return i * 20;
    })
    .attr("width", 10)
    .attr("height", 10)
    .style("fill", function(d) {
        var color = colors[dataset.indexOf(d)][1];
        return color;
    });

legend.selectAll('text')
    .data(dataset)
    .enter()
    .append("text")
    .attr("x", w - 52)
    .attr("y", function(d, i) {
        return i * 20 + 9;
    })
    .text(function(d) {
        var text = colors[dataset.indexOf(d)][0];
        return text;
    });

I know my Colors array/object probably isn't the most efficient way. So I'm open to adjusting that if it helps with the solution. Also, I would prefer that it is a Horizontal list instead of vertical.

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Apr 23, 2013 at 20:35 EnigmaRMEnigmaRM 7,63211 gold badges48 silver badges74 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

You need to use colors rather than dataset as parameter for the .data() of your legend. In order for that to work, colors has to be an array rather than an object:

var colors = [ ["Local", "#377EB8"],
               ["Global", "#4DAF4A"] ];

The code for creating the legend then bees:

var legendRect = legend.selectAll('rect').data(colors);

legendRect.enter()
    .append("rect")
    .attr("x", w - 65)
    .attr("width", 10)
    .attr("height", 10);

legendRect
    .attr("y", function(d, i) {
        return i * 20;
    })
    .style("fill", function(d) {
        return d[1];
    });

var legendText = legend.selectAll('text').data(colors);

legendText.enter()
    .append("text")
    .attr("x", w - 52);

legendText
    .attr("y", function(d, i) {
        return i * 20 + 9;
    })
    .text(function(d) {
        return d[0];
    });

Cf the updated fiddle.

发布评论

评论列表(0)

  1. 暂无评论