174 lines
5.6 KiB
JavaScript
174 lines
5.6 KiB
JavaScript
|
|
/** Class implementing the tileChart. */
|
|
class TileChart {
|
|
|
|
/**
|
|
* Initializes the svg elements required to lay the tiles
|
|
* and to populate the legend.
|
|
*/
|
|
constructor(tooltip){
|
|
|
|
let divTiles = d3.select("#tiles").classed("content", true);
|
|
this.margin = {top: 30, right: 20, bottom: 30, left: 50};
|
|
//Gets access to the div element created for this chart and legend element from HTML
|
|
let svgBounds = divTiles.node().getBoundingClientRect();
|
|
this.svgWidth = svgBounds.width - this.margin.left - this.margin.right;
|
|
this.svgHeight = this.svgWidth/2;
|
|
let legendHeight = 150;
|
|
//add the svg to the div
|
|
let legend = d3.select("#legend").classed("content",true);
|
|
|
|
//creates svg elements within the div
|
|
this.legendSvg = legend.append("svg")
|
|
.attr("width",this.svgWidth)
|
|
.attr("height",legendHeight)
|
|
.attr("transform", "translate(" + this.margin.left + ",0)")
|
|
this.svg = divTiles.append("svg")
|
|
.attr("width",this.svgWidth)
|
|
.attr("height",this.svgHeight)
|
|
.attr("transform", "translate(" + this.margin.left + ",0)")
|
|
|
|
this.tooltip = tooltip;
|
|
};
|
|
|
|
/**
|
|
* Returns the class that needs to be assigned to an element.
|
|
*
|
|
* @param party an ID for the party that is being referred to.
|
|
*/
|
|
chooseClass (party) {
|
|
if (party == "R"){
|
|
return "republican";
|
|
}
|
|
else if (party== "D"){
|
|
return "democrat";
|
|
}
|
|
else if (party == "I"){
|
|
return "independent";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates tiles and tool tip for each state, legend for encoding the
|
|
* color scale information.
|
|
*
|
|
* @param electionResult election data for the year selected
|
|
* @param colorScale global quantile scale based on the winning
|
|
* margin between republicans and democrats
|
|
*/
|
|
update (electionResult, colorScale){
|
|
|
|
//Calculates the maximum number of rows and columns
|
|
this.maxColumns = d3.max(electionResult, d => +d.Space) + 1;
|
|
this.maxRows = d3.max(electionResult, d => +d.Row) + 1;
|
|
|
|
// ******* TODO: PART IV *******
|
|
//Tansform the legend element to appear in the center and make a call to this element for it to display.
|
|
|
|
//Lay rectangles corresponding to each state according to the 'row' and 'column' information in the data.
|
|
|
|
//Display the state abbreviation and number of electoral votes on each of these rectangles
|
|
|
|
//Use global color scale to color code the tiles.
|
|
|
|
//HINT: Use .tile class to style your tiles;
|
|
// .tilestext to style the text corresponding to tiles
|
|
|
|
//Call the tool tip on hover over the tiles to display stateName, count of electoral votes
|
|
//then, vote percentage and number of votes won by each party.
|
|
//HINT: Use the .republican, .democrat and .independent classes to style your elements.
|
|
|
|
var self = this;
|
|
|
|
let statesG = this.svg.selectAll('g')
|
|
.data(electionResult);
|
|
|
|
statesG.exit().remove();
|
|
statesG = statesG.enter().append('g').merge(statesG);
|
|
|
|
let statesRect = statesG.selectAll('rect')
|
|
.data(function(d){
|
|
return d3.select(this).data()
|
|
});
|
|
|
|
//statesRect.exit().remove();
|
|
statesRect = statesRect.enter().append('rect').merge(statesRect);
|
|
|
|
statesRect
|
|
.attr('width', this.svgWidth/this.maxColumns)
|
|
.attr('height', this.svgHeight/this.maxRows)
|
|
.attr('x', function(d){
|
|
return (self.svgWidth/self.maxColumns)*(parseInt(d["Space"]))
|
|
})
|
|
.attr('y', function(d){
|
|
return (self.svgHeight/self.maxRows)*(parseInt(d["Row"]))
|
|
})
|
|
.attr('fill', function(d){
|
|
return colorScale(d["RD_Difference"])
|
|
})
|
|
.attr('space-row', function(d){
|
|
return d["Space"] + '-' + d["Row"];
|
|
})
|
|
.attr('stroke', '#ffffff')
|
|
.attr('stroke-width', 1)
|
|
.call(tip)
|
|
.on('mouseover', tip.show)
|
|
.on('mouseout', tip.hide)
|
|
|
|
let statesNameText = statesG.selectAll('text').filter('.stateName')
|
|
.data(function(d){
|
|
return d3.select(this).data()
|
|
});
|
|
|
|
//statesNameText.exit().remove();
|
|
statesNameText = statesNameText.enter().append('text').merge(statesNameText);
|
|
|
|
statesNameText
|
|
.attr('x', function(d){
|
|
let startX = (self.svgWidth/self.maxColumns)*(parseInt(d["Space"]))
|
|
return startX + (self.svgWidth/self.maxColumns)/2
|
|
})
|
|
.attr('y', function(d){
|
|
let startY = (self.svgHeight/self.maxRows)*(parseInt(d["Row"]))
|
|
return startY + (self.svgHeight/self.maxRows)/2
|
|
|
|
})
|
|
.attr('class', 'tilestext stateName')
|
|
.text(function(d){
|
|
return d["Abbreviation"]
|
|
})
|
|
.call(tip)
|
|
.on('mouseover', tip.show)
|
|
.on('mouseout', tip.hide)
|
|
|
|
let statesEVText = statesG.selectAll('text').filter('.stateEV')
|
|
.data(function(d){
|
|
return d3.select(this).data()
|
|
});
|
|
|
|
statesEVText.exit().remove();
|
|
statesEVText = statesEVText.enter().append('text').merge(statesEVText);
|
|
|
|
statesEVText
|
|
.attr('x', function(d){
|
|
let startX = (self.svgWidth/self.maxColumns)*(parseInt(d["Space"]))
|
|
return startX + (self.svgWidth/self.maxColumns)/2
|
|
})
|
|
.attr('y', function(d){
|
|
let startY = (self.svgHeight/self.maxRows)*(parseInt(d["Row"]))
|
|
return startY + (self.svgHeight/self.maxRows)/2 + 15;
|
|
})
|
|
.attr('class', 'tilestext stateEV')
|
|
.text(function(d){
|
|
return d["Total_EV"]
|
|
})
|
|
.call(tip)
|
|
.on('mouseover', tip.show)
|
|
.on('mouseout', tip.hide)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|