2

I'm trying to create a diverging stacked bar chart. I have two svg areas - one for yes votes and one for no votes. I need the no votes (the bars on the left of the image: https://i.stack.imgur.com/NJveR.png) to start on the right side of the scale and jut out towards the left side of the scale. The bars are created in the rectangles section, in the selNo selection. When creating these bars, how should I define the x attribute so that the bars start from the right? I've tried all sorts of combinations of adding and subtracting width, changing the scales, transforming the rects. I just can't seem to make it move where I want it!

Full Code:

var margin = { top: 50, right: 5, bottom: 20, left: 5 },
    width = 450 - margin.left - margin.right,
    height = 800 - margin.top - margin.bottom;

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

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

var votesNo = [];
var votesYes = [];

/////////GET DATA/////////////

//access votes route in Flask app
d3.json("/votes").then(function (data) {

    //loop through objects in route
    data.forEach(function (d) {

        //convert data to numeric
        demYes = +d.democratic.yes
        demNo = +d.democratic.no
        repYes = +d.republican.yes
        repNo = +d.republican.no
        indYes = +d.independent.yes
        indNo = +d.independent.no


        //push desired data to arrays
        votesYes.push(
            {
                "id": d._id,
                "name": d.bill.bill_id,
                "question": d.question,
                "description": d.description,
                "demYes": demYes,
                "repYes": repYes,
                "indYes": indYes,
            })
        votesNo.push(
            {
                "id": d._id,
                "name": d.bill.bill_id,
                "question": d.question,
                "description": d.description,
                "demNo": demNo,
                "repNo": repNo,
                "indNo": indNo,
            })
    });
    /////////////STACK GENERATORS//////////////

    //create stack generator for YES votes
    var stackGenYes = d3.stack()
        .keys(["demYes", "repYes", "indYes"]) //keys from votesYes
        .order(d3.stackorderDescending)   
    //use generator to create data array
    var stackedSeriesYes = stackGenYes(votesYes);
    console.log(stackedSeriesYes);

    //create stack generator for NO votes
    var stackGenNo = d3.stack()
        .keys(["demNo", "repNo", "indNo"]) //keys from votesNo
    //use generator to create data array
    var stackedSeriesNo = stackGenNo(votesNo);
    console.log(stackedSeriesNo);

    /////////////SCALE FUNCTIONS////////////

    //assign colors to parties
    var colorScale = d3.scaleOrdinal()
        .domain(["demYes", "repYes", "indYes"])
        .range(["#086fad", "#c7001e", "#8A2BE2"]);

    var yScale = d3.scaleBand()
        .domain(votesYes.map(d => d.id)) //unique identifiers
        .range([0, height])
        .padding(0.1);

    var xScaleYes = d3.scaleLinear()
        .domain([0, 535]) //num members of congress
        .range([0, width]);

    var xScaleNo = d3.scaleLinear()
        .domain([0, 535])
        .range([width, 0]);

    ////////////////RECTANGLES////////////////

    //create g tags for each YES key
    var selYes = d3.select("#svgYes")
        .select('g')
        .selectAll('g.seriesYes')
        .data(stackedSeriesYes)
        .join('g')
        .classed('series', true)
        .style('fill', (d) => colorScale(d.key)); //assign color
    //create YES bars
    selYes.selectAll('rect')
        .data(d => d)
        .join('rect')
        .attr('width', d => xScaleYes(d[1]) - xScaleYes(d[0])) //length of bars
        .attr('x', d => xScaleYes(d[0])) //bar starting point (x)
        .attr('y', d => yScale(d.data.id)) //bar starting point (y)
        .attr('height', 32) //thickness of bar

    //create g tags for each NO key
    var selNo = d3.select("#svgNo")
        .select('g')
        .selectAll('g.seriesNo')
        .data(stackedSeriesNo)
        .join('g')
        .classed('series', true)
        .style('fill', (d) => colorScale(d.key));
    //create NO bars
    selNo.selectAll('rect')
        .data(d => d)
        .join('rect')
        .attr('width', d => xScaleNo(d[0]) - xScaleNo(d[1])) //length of bars
        .attr('x', d => width - xScaleNo(d[0])) //bar starting point (x)
        .attr('y', d => yScale(d.data.id)) //bar starting point(y)
        .attr('height', 32); //thickness of bar
});
wisemantyr
  • 23
  • 4

0 Answers0