Skip to content

Instantly share code, notes, and snippets.

@ginseng666
Created October 4, 2017 14:02
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 ginseng666/a6aa39710bac300291e12231fbae49d3 to your computer and use it in GitHub Desktop.
Save ginseng666/a6aa39710bac300291e12231fbae49d3 to your computer and use it in GitHub Desktop.
offene Wahlen: Entwicklung Auszählungsgrad
time azg wahlberechtigte gueltig spoe oevp fpoe bzoe gruene
ref 1 6333109 4887309 1430206 1269656 857029 522933 509936
p0 0 6333109 4887309 1430206 1269656 857029 522933 509936
p1 0.37 6384308 3519053 1099176 970401 823408 143297 482771
p2 0.49 6384308 3662012 1185615 976461 842846 144180 512910
p3 0.64 6384308 3833025 1196191 1022354 924666 159606 530208
p4 0.77 6384308 4095197 1258605 1125876 962313 165746 582657
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Verlauf Auszählungsgrad</title>
</head>
<body>
<div id="container">
<div id="desc">Die Grafik zeigt den Verlauf des Gesamtergebnisses (nur Gemeinden, ohne Wahlkarten) am Wahlabend. Die X-Achse steht für den Auszählungsgrad."
</div>
<div id="chart">
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var percent = d3.formatLocale({"decimal":",", "thousands":".","grouping":[3],"currency":["€", ""]});
var margin = { top: 20, right: 20, bottom: 30, left: 20 };
var width = parseInt(d3.select("#chart").style("width"), 10) - margin.left - margin.right;
var height = window.innerHeight - margin.top - margin.bottom - 40 - parseInt(d3.select("#desc").style("height"), 10);
var color = {"oevp": "#191919", "spoe": "#ca5670", "fpoe": "#638ccc", "gruene": "#72a555", "kpoe": "#9F000F", "neos": "#F52887", "frank": "#E9AB17", "bzoe": "#F87431", "tie": "grey"};
var parties = ["spoe", "oevp", "fpoe", "gruene"];
var labels = {"spoe": "SPÖ", "oevp": "ÖVP", "fpoe": "FPÖ", "gruene": "GRÜNE", "neos": "NEOS", "frank": "FRANK", "kpoe": "KPÖ"};
var offset_x = 80;
var offset_y = 75;
var daten, verlauf;
var scale = {"y": d3.scaleLinear().domain([0, 0.5]).rangeRound([height - margin.top, margin.bottom]), "x": d3.scaleLinear().domain([0, 1]).range([margin.left, width - margin.right])};
var svg = d3.select("#chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id", "svg")
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
var line = d3.line().x(function(d) { return scale.x(+d.azg); });
var rsz;
window.onresize = resize; /*function()
{
clearTimeout(rsz);
rsz = setTimeout(resize, 500);
};*/
var q = d3.queue();
q.defer(d3.tsv, "daten.txt");
q.awaitAll(function(error)
{
if (!error)
{
daten = arguments[1][0];
verlauf = daten.filter(function(d) { return d.time != "ref"; });
draw();
}
});
function draw()
{
svg.append("defs").append("marker") //pfeil für notes
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 5)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 25)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5 L10,0 L0,5")
.attr("class","arrowHead");
svg.append("text")
.attr("x", scale.x(1) / 2)
.attr("y", scale.y(0))
.attr("dy", "2.5em")
.attr("class", "captions")
.text("Auszählungsgrad");
svg.append("text")
.attr("x", scale.x(0))
.attr("y", scale.y(0))
.attr("class", "start")
.attr("id", "left_up")
.attr("dy", "2.2em")
.style("text-anchor", "middle")
.text("Ergebnis");
svg.append("text")
.attr("x", scale.x(0))
.attr("y", scale.y(0))
.attr("dy", "3.4em")
.attr("class", "start")
.attr("id", "left_down")
.style("text-anchor", "middle")
.text("2013");
svg.append("text")
.attr("x", scale.x(1))
.attr("y", scale.y(0))
.attr("class", "start")
.attr("dy", "2.2em")
.attr("id", "right_up")
.style("text-anchor", "middle")
.text("Ergebnis");
svg.append("text")
.attr("x", scale.x(1))
.attr("y", scale.y(0))
.attr("dy", "3.4em")
.attr("class", "start")
.attr("id", "right_down")
.style("text-anchor", "middle")
.text("2017");
var positioning = svg.select(".captions").node().getBBox();
svg.append("line")
.attr("x1", scale.x(1) / 2 + positioning.width * 0.5 + 10)
.attr("x2", scale.x(1) / 2 + positioning.width * 2.5)
.attr("y1", positioning.y + positioning.height / 2)
.attr("y2", positioning.y + positioning.height / 2)
.attr("class", "arrows")
.attr("id", "arr_left")
.attr("marker-end", "url(#arrow)")
.style("stroke", "#000000");
svg.append("line")
.attr("x1", scale.x(1) / 2 - positioning.width * 0.5 - 10)
.attr("x2", scale.x(1) / 2 - positioning.width * 2.5)
.attr("y1", positioning.y + positioning.height / 2)
.attr("y2", positioning.y + positioning.height / 2)
.attr("class", "arrows")
.attr("id", "arr_right")
.attr("marker-end", "url(#arrow)")
.style("stroke", "#000000");
svg.append("line")
.attr("x1", scale.x(0))
.attr("x2", scale.x(1))
.attr("y1", scale.y(0))
.attr("y2", scale.y(0))
.attr("class", "axis")
.attr("id", "xaxis");
svg.append("line")
.attr("x1", scale.x(0))
.attr("x2", scale.x(0))
.attr("y1", scale.y(0))
.attr("y2", scale.y(1))
.attr("class", "axis")
.attr("id", "yaxis");
svg.selectAll(".gridv")
.data(d3.range(0.25, 1, 0.25))
.enter()
.append("line")
.attr("x1", function(d) { return scale.x(d); })
.attr("x2", function(d) { return scale.x(d); })
.attr("y1", scale.y(0))
.attr("y2", scale.y(1))
.attr("class", "gridv");
svg.selectAll(".gridh")
.data(d3.range(0.15, 0.5, 0.15))
.enter()
.append("line")
.attr("x1", scale.x(0))
.attr("x2", scale.x(1))
.attr("y1", function(d) { return scale.y(d); })
.attr("y2", function(d) { return scale.y(d); })
.attr("class", "gridh");
svg.selectAll(".labelsv")
.data(d3.range(0.25, 1, 0.25))
.enter()
.append("text")
.attr("x", function(d) { return scale.x(d); })
.attr("y", scale.y(0))
.attr("dy", "1em")
.attr("class", "labelsv")
.text(function(d) { return percent.format(",.0%")(d); });
svg.selectAll(".labelsh")
.data(d3.range(0.15, 0.5, 0.15))
.enter()
.append("text")
.attr("x", scale.x(0))
.attr("y", function(d) { return scale.y(d); })
.attr("dx", "-1em")
.attr("dy", "0.3em")
.attr("class", "labelsh")
.text(function(d) { return percent.format(",.0%")(d); });
svg.selectAll(".dots")
.data(parties)
.enter()
.append("circle")
.attr("cx", function(d) { return scale.x(0); })
.attr("cy", function(d) { return scale.y(+daten[0][d] / +daten[0].gueltig); })
.attr("r", 10)
.attr("class", "dots")
.style("fill", function(d) { return color[d]; });
svg.append("line")
.attr("class", "current");
svg.append("text")
.attr("y", scale.y(0) - 2)
.attr("class", "currenttext");
for (var i = 0, len = parties.length; i < len; i++)
{
line.y(function(d) { return scale.y(+d[parties[i]] / +d.gueltig); });
svg.append("path")
.datum(verlauf)
.attr("d", line)
.attr("class", "lines")
.attr("id", "line_" + parties[i])
.style("stroke", color[parties[i]]);
svg.append("circle")
.attr("cx", function(d) { return scale.x(verlauf[verlauf.length - 1].azg); })
.attr("cy", function(d) { return scale.y(+verlauf[verlauf.length - 1][parties[i]] / +verlauf[verlauf.length - 1].gueltig); })
.attr("r", 10)
.attr("class", "endpoints")
.attr("id", "endpoint_" + parties[i])
.style("stroke", color[parties[i]])
.on("mouseover", function()
{
svg.select(".current")
.attr("x1", scale.x(verlauf[verlauf.length - 1].azg))
.attr("x2", scale.x(verlauf[verlauf.length - 1].azg))
.attr("y1", scale.y(1))
.attr("y2", scale.y(0))
.style("display", "block");
svg.select(".currenttext")
.attr("x", scale.x(verlauf[verlauf.length - 1].azg))
.attr("dx", "0.2em")
.style("display", "block")
.text(percent.format(",.0%")(verlauf[verlauf.length - 1].azg));
})
.on("mouseout", function() { svg.selectAll(".current, .currenttext").style("display", "none"); });
svg.selectAll(".points_" + parties[i])
.data(verlauf.slice(1, verlauf.length - 1))
.enter()
.append("circle")
.attr("cx", function(d) { return scale.x(d.azg); })
.attr("cy", function(d) { return scale.y(+d[parties[i]] / +d.gueltig); })
.attr("r", 5)
.attr("class", "points_" + parties[i])
.style("fill", color[parties[i]])
.on("mouseover", function(d)
{
svg.select(".current")
.attr("x1", scale.x(d.azg))
.attr("x2", scale.x(d.azg))
.attr("y1", scale.y(1))
.attr("y2", scale.y(0))
.style("display", "block");
svg.select(".currenttext")
.attr("x", scale.x(d.azg))
.attr("dx", "0.2em")
.style("display", "block")
.text(percent.format(",.0%")(d.azg));
})
.on("mouseout", function() { svg.selectAll(".current, .currenttext").style("display", "none"); });
}
}
function resize()
{
width = parseInt(d3.select("#chart").style("width"), 10) - margin.left - margin.right;
height = window.innerHeight - margin.top - margin.bottom - 40 - parseInt(d3.select("#desc").style("height"), 10);
scale.y.rangeRound([height - margin.top, margin.bottom]);
scale.x.range([margin.left, width - margin.right]);
d3.select("#svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.select("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
svg.select(".captions")
.attr("x", scale.x(1) / 2)
.attr("y", scale.y(0));
svg.select("#left_up")
.attr("x", scale.x(0))
.attr("y", scale.y(0));
svg.select("#left_down")
.attr("x", scale.x(0))
.attr("y", scale.y(0));
svg.select("#right_up")
.attr("x", scale.x(1))
.attr("y", scale.y(0));
svg.select("#right_down")
.attr("x", scale.x(1))
.attr("y", scale.y(0));
var positioning = svg.select(".captions").node().getBBox();
svg.select("#arr_right")
.attr("x1", scale.x(1) / 2 + positioning.width * 0.5 + 10)
.attr("x2", scale.x(1) / 2 + positioning.width * 2.5)
.attr("y1", positioning.y + positioning.height / 2)
.attr("y2", positioning.y + positioning.height / 2);
svg.select("#arr_left")
.attr("x1", scale.x(1) / 2 - positioning.width * 0.5 - 10)
.attr("x2", scale.x(1) / 2 - positioning.width * 2.5)
.attr("y1", positioning.y + positioning.height / 2)
.attr("y2", positioning.y + positioning.height / 2);
svg.select("#xaxis")
.attr("x1", scale.x(0))
.attr("x2", scale.x(1))
.attr("y1", scale.y(0))
.attr("y2", scale.y(0));
svg.select("#yaxis")
.attr("x1", scale.x(0))
.attr("x2", scale.x(0))
.attr("y1", scale.y(0))
.attr("y2", scale.y(1));
svg.selectAll(".gridv")
.attr("x1", function(d) { return scale.x(d); })
.attr("x2", function(d) { return scale.x(d); })
.attr("y1", scale.y(0))
.attr("y2", scale.y(1));
svg.selectAll(".gridh")
.attr("x1", scale.x(0))
.attr("x2", scale.x(1))
.attr("y1", function(d) { return scale.y(d); })
.attr("y2", function(d) { return scale.y(d); });
svg.selectAll(".labelsv")
.attr("x", function(d) { return scale.x(d); })
.attr("y", scale.y(0));
svg.selectAll(".labelsh")
.attr("x", scale.x(0))
.attr("y", function(d) { return scale.y(d); });
svg.selectAll(".dots")
.attr("cx", function(d) { return scale.x(0); })
.attr("cy", function(d) { return scale.y(+daten[0][d] / +daten[0].gueltig); });
svg.select(".currenttext")
.attr("y", scale.y(0) - 2);
for (var i = 0, len = parties.length; i < len; i++)
{
line.y(function(d) { return scale.y(+d[parties[i]] / +d.gueltig); });
svg.select("#line_" + parties[i])
.attr("d", line);
svg.select("#endpoint_" + parties[i])
.attr("cx", function(d) { return scale.x(verlauf[verlauf.length - 1].azg); })
.attr("cy", function(d) { return scale.y(+verlauf[verlauf.length - 1][parties[i]] / +verlauf[verlauf.length - 1].gueltig); });
svg.selectAll(".points_" + parties[i])
.attr("cx", function(d) { return scale.x(d.azg); })
.attr("cy", function(d) { return scale.y(+d[parties[i]] / +d.gueltig); })
}
}
</script>
</body>
</html>
body
{
margin: 0;
padding: 0;
font-size: 14px;
}
svg
{
overflow: hidden;
}
#container
{
width: 95vw;
margin: 1vw auto 0 auto;
}
.axis, .gridv, .gridh, .current
{
stroke: #000000;
stroke-opacity: 0.2;
}
.gridv, .gridh
{
stroke-dasharray: 1, 3;
}
.captions, .labelsh, .labelsv, .start
{
stroke: none;
fill: #000000;
font-size: 12px;
}
.captions
{
text-anchor: middle;
font-size: 14px;
display: none;
}
.labelsh, .labelsv
{
text-anchor: middle;
}
.lines
{
fill: none;
stroke-width: 3px;
stroke-dasharray: 4, 4;
}
.endpoints, .points
{
fill: #ffffff;
stroke-width: 4px;
}
.arrows
{
display: none;
}
@media screen and (min-width: 640px)
{
.arrows, .captions
{
display: block;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment