Skip to content

Instantly share code, notes, and snippets.

@tomgp
Last active May 28, 2019 04:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tomgp/59b5d482551ca14a4063 to your computer and use it in GitHub Desktop.
Save tomgp/59b5d482551ca14a4063 to your computer and use it in GitHub Desktop.
US senate icon array
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-scale')) :
typeof define === 'function' && define.amd ? define(['exports', 'd3-scale'], factory) :
(factory((global.d3_iconarray = global.d3_iconarray || {}),global.d3));
}(this, function (exports,d3) { 'use strict';
function iconArrayLayout() {
var width = undefined;
var height = undefined;
var widthFirst = true;
var maxDimension = undefined;
function layout(data){
//work our missing height, width stuff
setDimensions(data.length);
return data.map(function(d,i){
return {
data:d,
position:position(i)
};
});
}
function position(i){
if(isNaN(width) || isNaN(height)){
console.log('Warning: width/height undefined')
return 0;
}
if(widthFirst){
return {
x: i % width,
y: Math.floor( i/width )
};
}else{
return {
x: Math.floor( i/height ),
y: i % height
};
}
}
function setDimensions(l){
//neither width or height is defined
if(isNaN(width) && isNaN(height)){
console.log('no width or height');
if(widthFirst){
width = Math.ceil( Math.sqrt(l) );
height = Math.ceil( l / width );
}else{
height = Math.ceil( Math.sqrt(l) );
width = Math.ceil( l / height );
}
}else if(isNaN(width)){ //width undefined
width = Math.ceil( l / height );
}else if(isNaN(height)){ //height undefined
height = Math.ceil( l / width );
}
}
layout.maxDimension = function(x){
var itemPosition = position(x);
if(widthFirst){
var x = Math.max(itemPosition.x, width);
return Math.max(x, itemPosition.y);
}
var y = Math.max(itemPosition.y, height);
return Math.max(y, itemPosition.x);
}
layout.position = function(x){
return position(x);
}
layout.width = function(x){
if(x === undefined) return width;
width = x;
return layout;
};
layout.height = function(x){
if(x === undefined) return height;
height = x;
return layout;
};
layout.widthFirst = function(b){
if(b === undefined) return widthFirst;
widthFirst = b;
return layout;
};
return layout;
};
function iconArrayScale(){
var domain = [0,100];
var range = [0,100];
var gapInterval = 10;
var gapSize = 0; //default no change
var notionalScale = d3.scaleLinear()
.domain(domain)
.range(range);
function scale(domainValue){
var rangeValue = 20;
var adjustedDomainValue = domainValue + Math.floor(domainValue/gapInterval)*gapSize;
//console.log(notionalScale.domain());
return rangeValue = notionalScale(adjustedDomainValue);
}
function rescale(){
//calculate an adjusted domain
var domainLength = (domain[1] - domain[0]) * gapSize;
var gaps = Math.ceil( domainLength/ gapInterval );
var adjustedDomain = [ domain[0], domain[1] + gaps ];
//calculate an adjusted range
notionalScale.domain(adjustedDomain)
.range(range);
}
scale.gapInterval = function(x){
if(!x) return gapInterval;
gapInterval = x;
rescale();
return scale;
};
scale.gapSize = function(x){
if(isNaN(x)) return gapSize;
gapSize = x;
rescale();
return scale;
}
scale.domain = function(array){
if(!array) return domain;
domain = array;
rescale();
return scale;
};
scale.range = function(array){
if(!array) return range;
range = array;
rescale();
return scale;
};
rescale();
return scale;
}
var version = "0.0.1";
exports.version = version;
exports.layout = iconArrayLayout;
exports.scale = iconArrayScale;
}));
state result.winner result.caucus result.r result.d result.i result.reporting result.time seatid encumbentparty Cook Political Rating election
AK AK1 D Tossup yes
AL R R 100 0 8:00 EST AL1 R Solid Republican yes
AR R R 56.5 40 73 1:18 EST AR1 D Tossup yes
CO R R 50.3 44.3 87 1:41 EST CO1 D Tossup yes
DE D D 42.2 55.8 100 00:48 EST DE1 D Solid Democratic yes
GA R R 53 45.1 99.6 1:42 EST GA1 R Tossup yes
HI D D 25.2 72.5 7.7 1:42 EST HI1 D Solid Democratic yes
IA R R 52.1 43.8 98.6 1:46 EST IA1 D Tossup yes
ID R R 66.39 33.61 55 1:15 EST ID1 R Solid Republican yes
IL D D 43.3 52.92 97.92 00:51 EST IL1 D Solid Democratic yes
KS R R 53.07 42.72 69.4 00:41 EST KS1 R Tossup yes
KY R R 56.2 40.7 100 2:07 EST KY1 R Lean Republican yes
LA 42.1 41 100 1:50 EST LA1 D Tossup yes
MA D D 37.8 62.2 97.24 00:51 EST MA1 D Solid Democratic yes
ME R R 68.1 32 63.9 1:52 EST ME1 R Solid Republican yes
MI D D 41.3 54.7 93.9 1:55 EST MI1 D Lean Democratic yes
MN D D 42.8 53.3 92.2 1:55 EST MN1 D Likely Democratic yes
MS R R 59.2 38.6 96.5 00:49 EST MS1 R Likely Republican yes
MT R R 57.48 40.46 59 1:15 EST MT1 D Solid Republican yes
NC R R 49.1 47.2 3.7 96.6 11:25 EST NC1 D Tossup yes
NE R R 64.9 30.91 66 1:15 EST NE1 R Solid Republican yes
NH D D 48.4 51.6 87.4 00:53 EST NH1 D Tossup yes
NJ D D 42.06 56.11 95.53 00:43 EST NJ1 D Solid Democratic yes
NM D D 44.97 55.03 65 00:44 EST NM1 D Solid Democratic yes
OK R R 68 28.5 100 1:56 EST OK1 R Solid Republican yes
OK R R 67.9 29 100 1:56 EST OK2 R Solid Republican yes
OR D D 38.2 55.14 65.1 00:46 EST OR1 D Likely Democratic yes
RI D D 29.5 70.5 99.8 1:58 EST RI1 D Solid Democratic yes
SC R R 54.5 38.9 99 1:59 EST SC1 R Solid Republican yes
SC R R 61.2 37.1 99 2:00 EST SC2 D Solid Republican yes
SD R R 51.6 28.4 16.8 87.5 2:00 EST SD1 D Lean Republican yes
TN R R 61.9 31.9 99 2:03 EST TN1 R Solid Republican yes
TX R R 61.6 34.4 97 2:03 EST TX1 R Solid Republican yes
VA VA1 D Likely Democratic yes
WV R R 62 34.6 98.6 2:06 EST WV1 D Likely Republican yes
WY R R 72.3 17.6 100 2:06 EST WY1 R Solid Republican yes
AK AK2 R
AL AL2 R
AR AR2 R
AZ AZ1 R
AZ AZ2 R
CA CA1 D
CA CA2 D
CO CO2 D
CT CT1 D
CT CT2 D
DE DE2 D
FL FL1 R
FL FL2 D
GA GA2 R
HI HI2 D
IA IA2 R
ID ID2 R
IL IL2 R
IN IN1 R
IN IN2 D
KS KS2 R
KY KY2 R
LA LA2 R
MA MA2 D
MD MD1 D
MD MD2 D
ME ME2 I
MI MI2 D
MN MN2 D
MO MO1 D
MO MO2 R
MS MS2 R
MT MT2 D
NC NC2 R
ND ND1 R
ND ND2 D
NE NE2 R
NH NH2 R
NJ NJ2 D
NM NM2 D
NV NV1 D
NV NV2 R
NY NY1 D
NY NY2 D
OH OH1 R
OH OH2 D
OR OR2 D
PA PA1 D
PA PA2 R
RI RI2 D
SD SD2 R
TN TN2 R
TX TX2 R
UT UT1 R
UT UT2 R
VA VA2 D
VT VT1 D
VT VT2 I
WA WA1 D
WA WA2 D
WI WI1 D
WI WI2 R
WV WV2 D
WY WY2 R
<!DOCTYPE html>
<html>
<head>
<title>Simple icon array example</title>
<script src="//d3js.org/d3.v4.0.0-alpha.18.min.js" charset="utf-8"></script>
<script type="text/javascript" src="d3-iconarray.js"></script>
<style type="text/css">
*{
font-family: sans-serif;
letter-spacing: 1px;
}
.R, .I{
fill:#F00;
}
.Solid-Republican{
stroke:#F00;
stroke-width:2;
fill: none;
}
.Likely-Republican{
stroke:#F00;
stroke-width:2;
stroke-dasharray:4 2;
fill: none;
}
.Lean-Republican{
stroke:#F00;
stroke-width:2;
stroke-dasharray:2 4;
fill: none;
}
.Tossup{
stroke:#CCC;
stroke-width:2;
fill: none;
}
.Lean-Democratic{
stroke:#00F;
stroke-width:2;
stroke-dasharray:2 4;
fill: none;
}
.Likely-Democratic{
stroke:#00F;
stroke-width:2;
stroke-dasharray:4 2;
fill: none;
}
.Solid-Democratic{
stroke:#00F;
stroke-width:2;
fill: none;
}
.D{
fill:#00F;
}
.key-element text{
font-size: 12px
}
</style>
</head>
<body>
<h1>2014 US senate election</h1>
<p>This graphic shows the 100 seats of the US senate in the run up to the 2014 election. It indicates which were up for election and what their result was expected to be according to <a href="http://cookpolitical.com/senate/charts/race-ratings/8108">The Cook Political Report</a></p>
<div id="senate-example">
</div>
</body>
<script type="text/javascript">
var order = [
'R',
'Solid Republican',
'Likely Republican',
'Lean Republican',
'Tossup',
'Lean Democratic',
'Likely Democratic',
'Solid Democratic',
'D' ]
var width = 600, height = 400,
margin = {top:20,left:20,bottom:20,right:20};
var plotWidth = width - (margin.left + margin.right);
var svg = d3.select('#senate-example')
.append('svg')
.attr('width',width)
.attr('height', height)
.append('g')
.attr('transform','translate('+margin.left+','+margin.top+')')
d3.csv('data-senate-2014.csv', function(data){
var sorted = data.map(function(d){
if (d.election == "" || d.election == undefined){
d['Cook Political Rating'] = d.encumbentparty;
}
return d;
})
.sort(function(a,b){
return order.indexOf(a['Cook Political Rating']) - order.indexOf(b['Cook Political Rating']);
});
var layout = d3_iconarray.layout()
.height(5)
.widthFirst(false);
var grid = layout(sorted);
var scale = d3_iconarray.scale()
.domain([0, layout.maxDimension(sorted.length)])
.range([0, plotWidth])
.gapInterval(10)
.gapSize(1.5);
svg.selectAll('circle')
.data(grid, function(d){ return d.data.seatid; })
.enter()
.append('circle')
.attr('r',function(d){
if(d.data.election){
return 5
}
return 2
})
.attr('cx',function(d){
return scale(d.position.x);
})
.attr('cy',function(d){
return scale(d.position.y);
})
.attr('class',function(d){
return d.data["Cook Political Rating"].replace(/\s/g,'-')
});
//key
var columns = [
['R','Solid Republican','Likely Republican','Lean Republican'],
['Tossup'],
['D','Solid Democratic','Likely Democratic','Lean Democratic']
];
d3.select('svg').selectAll('g.key-column')
.data(columns).enter()
.append('g')
.attr('class','key-column')
.attr('transform',function(d,i){
return 'translate('+(margin.left + (i*plotWidth/columns.length))+','+ (margin.top*4 + scale(layout.height())) +')';
})
.each(function(columnData){
d3.select(this)
.selectAll('g.key-element')
.data(columnData)
.enter()
.append('g')
.attr('class','key-element')
.attr('transform',function(d,i){
return 'translate(0,'+scale(i)+')';
})
.call(function(parent){
parent.append('circle')
.attr('cy',-5)
.attr('r',function(d){
if(d==='D'||d==='R'){
return 2
}
return 5
})
.attr('class',function(d){
return d.replace(/\s/g,'-')
});
parent.append('text')
.attr('dx', margin.left)
.text(function(d){
if(d==='R') return 'Rep (no election)'
if(d==='D') return 'Dem (no election)'
if(d==='Tossup') return 'Tossup ¯\\_(ツ)_/¯' //added the shrugging guy to make the key look abalanced ¯\_(ツ)_/¯
return d;
})
});
});
});
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment