Skip to content

Instantly share code, notes, and snippets.

@sugi2000
Last active July 8, 2016 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sugi2000/2548f07e4de3291c24c3290f60b64f28 to your computer and use it in GitHub Desktop.
Save sugi2000/2548f07e4de3291c24c3290f60b64f28 to your computer and use it in GitHub Desktop.
第47回衆議院議員総選挙 比例代表 北海道ブロック
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body, .axis text{
font: 14px sans-serif;
font-weight: bold;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path, .x.axis line {
display: none;
}
.y.axis text {
font-size: 10px;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<body>
<form>
<label><input type="radio" name="mode" value="parties" checked>党派別得票数</label>
<label><input type="radio" name="mode" value="winners">当選人数</label>
</form>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 60};
var width = 900;
var height = 550;
var svg = d3.select('body')
.append('svg')
.attrs({
"width": width + margin.left + margin.right,
"height": height + margin.top + margin.bottom,
})
.append('g')
.attr('transform', 'translate('+margin.left+','+margin.top+')');
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(.1);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var partyColor = d3.scaleOrdinal(d3.schemeCategory10);
var quotient = function(d) { return d.votes / d.denominator; };
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var partyVotes;
var winners;
var pickTimer;
var seats = 8; // 定数
var simulateSeats = 20; // シミュレート定数
var partyKey = '政党';
var votesKey = '得票数';
d3.csv('result.csv', function(error, data){
if (error) { throw error; }
data.forEach(function(d){
d.party = d[partyKey];
d.votes = +d[votesKey],
d.denominator = 1;
d.winners = [];
});
data.sort(function(a,b){ return b[votesKey] - a[votesKey]; });
x.domain(data.map(function(d) { return d[partyKey]; }));
y.domain([0, d3.max(data.map(function(d){return d[votesKey];}))]);
console.log(data);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
// .call(d3.axisLeft(y).ticks(10).tickFormat(d3.formatPrefix('.1', 1e6)))
.append("text")
// .attr("transform", "rotate(-90)")
.attr("x", "-2em")
.attr("y", y(y.ticks(10).shift()))
.attr("dy", "2em")
.attr("text-anchor", "end")
.attr("fill", "#000")
.text(votesKey);
var g = svg.selectAll('.party')
.data(data)
.enter()
.append('g')
.attrs({
class: function(d){ return 'party ' + d.party; },
transform: function(d,i) { return 'translate('+ x(d.party) +', 0)' },
});
var partyVotesBg = g.selectAll('.party-votes-bg')
.data(function(d){return [d];})
.enter()
.append('rect')
.attrs({
class: 'party-votes-bg',
x: 0,
y: function(d){ return y(d.votes); },
width: x.bandwidth(),
height: function(d){ return y(0) - y(d.votes); },
fill: function(d){ return d3.hsl(partyColor(d.party)).brighter(); },
// fill: '#f0f0f0',
});
partyVotes = g.selectAll('.party-votes')
.data(function(d){return [d];})
.enter()
.append('rect')
.attrs({
class: 'party-votes',
x: 0,
y: function(d){ return y(d.votes); },
width: x.bandwidth(),
height: function(d){ return y(0) - y(d.votes); },
fill: function(d){ return partyColor(d.party); },
});
});
function getFirstPartyVotes() {
var maxVotes = 0;
var firstParty;
partyVotes.nodes().forEach(function(d){
var party = d3.select(d);
if (quotient(party.data()[0]) > maxVotes) {
firstParty = party;
maxVotes = quotient(party.data()[0]);
}
});
// console.log(firstParty, maxVotes);
return firstParty;
}
function pickWinner() {
var numWinner = d3.selectAll('.winners').nodes().length;
if (numWinner >= simulateSeats) {
return;
}
var firstPartyVotes = getFirstPartyVotes();
var party = d3.select(firstPartyVotes.node().parentNode);
var data = party.data()[0];
data.winners.push({
party: data.party,
votes: quotient(data),
order: numWinner+1,
});
var padding = 4;
var size = x.bandwidth() / 2 - padding * 2;
var winners = party.selectAll('.winners')
.data(function(d) {return d.winners; })
.enter()
.append('circle')
.attrs({
class: 'winners',
cx: function(d, i) { return padding + ((i % 2) + .5) * (size + padding); },
cy: function(d, i) { return padding + (Math.floor(i / 2) + .5) * (size + padding); },
r: 0,
stroke: '#fff',
'stroke-width': 2,
fill: function(d) {
if (numWinner < seats) {
return partyColor(d.party);
} else {
return 'rgba(0, 0, 0, 0.5)';
}
},
});
var timer = setTimeout(function(){
party.selectAll('.winners-order')
.data(function(d) {return d.winners; })
.enter()
.append('text')
.attrs({
class: 'winners-order',
x: function(d, i) { return padding + ((i % 2)+.5) * (size + padding); },
y: function(d, i) { return padding + (Math.floor(i / 2)+.6) * (size + padding); },
'text-anchor': 'middle',
'font-weight': 'bold',
fill: '#fff',
})
.text(function(d,i){return d.order;});
}, 250);
data.denominator++;
partyVotes
.data(function(d){ return [d]; })
.transition()
.duration(250)
.attrs({
y: function(d){ return y(quotient(d)); },
height: function(d){ return y(0) - y(quotient(d)); },
});
winners
.transition()
.duration(250)
.attrs({
r: size / 2,
});
pickTimer = setTimeout(function(){
pickWinner();
}, 400);
}
d3.selectAll("input").on("change", change);
function change() {
removeWinners();
switch(this.value) {
case 'parties':
transitionParties();
break;
case 'winners':
transitionParties();
setTimeout(function(){
pickWinner();
}, 1000);
break;
}
}
function removeWinners() {
clearTimeout(pickTimer);
d3.selectAll('.party').data().forEach(function(d){
d.denominator = 1;
});
svg.selectAll('.party').data().forEach(function(d){
d.winners = [];
});
var winners = svg.selectAll('.winners, .winners-order')
.data([]);
winners.exit().remove();
}
function transitionParties(callback) {
svg.selectAll('.votes')
.transition()
.duration(1000)
.attrs({
fill: '#f0f0f0',
});
partyVotes
.data(function(d){ return [d]; })
.transition()
.duration(1000)
.attrs({
width: x.bandwidth(),
y: function(d){ return y(quotient(d)); },
height: function(d){ return y(0) - y(quotient(d)); },
});
// .call(endall, callback);
}
function endall(transition, callback) {
if (!callback) callback = function(){};
if (transition.size() === 0) { callback() }
var n = 0;
transition
.each(function() { ++n; })
.each("end", function() { if (!--n) callback.apply(this, arguments); });
}
d3.select(self.frameElement).style("height", height + margin.top + margin.bottom + "px");
</script>
</body>
</html>
政党 得票数
自由民主党 744748
民主党 688922
維新の党 247342
公明党 307534
日本共産党 302251
次世代の党 38342
社会民主党 53604
幸福実現党 12267
支持政党なし 104854
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment