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
});