Changing the colors of each of the Stacked Bar cha

2020-04-18 07:13发布

问题:

This involved the assignment of different colors to each bars of the stacked bar charts as currently there is only single color in all the four bars and colors are changing in the stacked one but I am trying to assign different colors to all the four bars as well the stacked value.

Here is the code

    var margin = {
            top: 20,
            right: 160,
            bottom: 35,
            left: 30
          };

          var width = 960 - margin.left - margin.right,
            height = 600 - margin.top - margin.bottom;

          var svg = d3.select("body")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


          /* Data in strings like it would be if imported from a csv */

          var data = [{
              year: "A",
              redDelicious: "10",
              mcintosh: "5",
              oranges: "19"
            }, {
              year: "B",
              redDelicious: "12",
              mcintosh: "0",
              oranges: "15"
            }, {
              year: "C",
              redDelicious: "05",
              mcintosh: "0",
              oranges: "28"
            }, {
              year: "D",
              redDelicious: "14",
              mcintosh: "0",
              oranges: "12"
            },

          ];
          $("#btn").on("click", function(){
            d3.selectAll("svg > g > g").remove();
            data[1].mcintosh = (Number(data[1].mcintosh) + 1).toString();
            console.log(1,data);
            update();
          });
          update();
    function update(){
          var orangeData = data.map(function(d) {
            return {
              year: d.year,
              oranges: +d.oranges
            }
          });
          console.log(orangeData)



          // Transpose the data into layers
          var dataset = d3.layout.stack()(["redDelicious", "mcintosh"].map(function(skillset) {
            return data.map(function(d) {
              return {
                x: d.year,
                y: +d[skillset]
              };
            });
          }));
          console.log(dataset)

          // Set x, y and colors
          var x = d3.scale.ordinal()
            .domain(dataset[0].map(function(d) {
              return d.x;
            }))
            .rangeRoundBands([10, width - 10], 0.02);

          var y = d3.scale.linear()
            .domain([0, d3.max(dataset, function(d) {
              return d3.max(d, function(d) {
                return d.y0 + d.y;
              });
            })])
            .range([height, 0]);

          var colors = ["#b33040", "#d9d574"];
           var backcolors = ["red", "blue","green","pink"];


          // Define and draw axes
          var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left")
            .ticks(5)
            .tickSize(-width, 0, 0)
            .tickFormat(function(d) {
              return d
            });

          var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");
          //  .tickFormat(d3.time.format("%Y"));

          svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);

          svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

            // Creating the Average Bar for the Semester
            svg.selectAll(".bar1").data(orangeData).enter().append("g")
            .attr("class", "bar1").append("rect")
            .attr("x", function(d) {
              return x(d.year) ; // center it
            })
            .attr("width", x.rangeBand()) // make it slimmer
            .attr("y", function(d) {
              return y(d.oranges);
            })
            .attr("height", function(d) {
              return height - y(d.oranges);
            });



          // Create groups for each series, rects for each segment in Stacked Bar 
          var groups = svg.selectAll("g.cost")
            .data(dataset)
            .enter().append("g")
            .attr("class", "cost")
            .style("fill", function(d, i) {
              return colors[i];
            });

          var rect = groups.selectAll("rect")
            .data(function(d) {
              return d;
            })
            .enter()
            .append("rect")
            .attr("x", function(d) {
              return x(d.x)  + 20 ;
            })
            .attr("y", function(d) {
              return y(d.y0 + d.y);
            })
            .attr("height", function(d) {
              return y(d.y0) - y(d.y0 + d.y);
            })
            .attr("width", x.rangeBand() -40 );
            }

Here is the working fiddle

回答1:

First, set your colours array:

var colors = ['#7fc97f','#beaed4','#fdc086','#ffff99','#386cb0','#f0027f','#bf5b17','#666666'];

Then, in your rectangles (not in your groups), set the fill of each bar using the parent's index:

.attr("fill", function(d, i, j) {
      return colors[(j*4)+i];
 });

Here, the magic number "4" is the number of groups. Change it accordingly (if you create more bars).

Here is your fiddle: https://fiddle.jshell.net/747beqqc/