admin管理员组

文章数量:1392054

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.

本文标签: javascriptd3js Create legend for bar chartStack Overflow