xxxxxxxxxx
<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>Bundesländer</title>
</head>
<body>
<div id="container">
<div id="desc">Die Grafik zeigt wechselweise das Bundesland-Ergebnis jeder (?) Partei zum aktuell ausgezählten Stand bzw. den Anteil des Bundesland-Ergebnisses am Partei-Ergebnis insgesamt. Ebenso sichtbar ist die Zahl der pro Bundesland bereits ausgezählten Gemeinden.
</div>
<div id="buttons">
<div class="button pressed" id="result" onclick="change(this.id)">Ergebnis im Bundesland</div>
<div class="button" id="share" onclick="change(this.id)">Anteil am Partei-Gesamtergebnis</div>
</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) - parseInt(d3.select("#buttons").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", "neos", "frank", "kpoe"];
var labels = {"spoe": "SPÖ", "oevp": "ÖVP", "fpoe": "FPÖ", "gruene": "GRÜNE", "neos": "NEOS", "frank": "FRANK", "kpoe": "KPÖ"};
var laender, aut, namen, spacer;
var offset_x = 80;
var offset_y = 75;
var max = {"result": 0, "share": 0, "use": 0};
var scale = {"result": d3.scaleLinear(), "share": d3.scaleLinear(), "azg": d3.scaleLinear().domain([0, 1]), "y": d3.scaleBand().domain(parties.concat(["", "gemeinden"])).rangeRound([offset_y + margin.top, height - margin.bottom]).paddingOuter(0.1).paddingInner(0.2)};
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 rsz;
window.onresize = function()
{
clearTimeout(rsz);
rsz = setTimeout(resize, 500);
};
var azg = d3.range(9).map(function() { return Math.random(); }); //auszählungsgrad pro bundesland, muss aus der api kommen
var q = d3.queue();
q.defer(d3.tsv, "daten_2013in2017.txt");
q.awaitAll(function(error)
{
if (!error)
{
var bls = arguments[1][0].filter(function(d) { return d.gkz.slice(-4) == "0000"; });
aut = bls.filter(function(d) { return d.gkz.slice(-5) == "00000"; });
laender = bls.slice(0, 9);
namen = laender.map(function(d) { return d.name; });
for (var i = 0, len = laender.length; i < len; i++)
{
var highest = d3.max(parties.map(function(d) { return +laender[i][d] / +laender[i].gueltig; }));
if (highest > max.result) max.result = Math.ceil(highest * 10) / 10; //höchstes bundesland-ergebnis
var highest = d3.max(parties.map(function(d) { return +laender[i][d] / +aut[0][d]; }));
if (highest > max.share) max.share = Math.ceil(highest * 10) / 10; //höcherst anteil eines bundesland-ergebnisses am parteiergebnis;
}
max.use = Math.max(max.result, max.share);
draw();
}
});
function draw()
{
spacer = Math.floor((width - offset_x) / laender.length);
var gk = Math.atan((offset_y - margin.top) / (spacer / 1.5)) * 180 / Math.PI;
scale.result.domain([0, max.use]).range([0, spacer]);
scale.share.domain([0, max.use]).range([0, spacer]);
scale.azg.range([0, spacer - 1]);
for (var i = 0; i < namen.length; i++)
{
svg.append("line")
.attr("x1", offset_x + spacer * i)
.attr("x2", offset_x + spacer * i)
.attr("y1", offset_y)
.attr("y2", height)
.attr("class", "grid_v");
svg.append("line")
.attr("x1", offset_x + spacer * i + spacer / 1.5)
.attr("x2", offset_x + spacer * i)
.attr("y1", margin.top)
.attr("y2", offset_y)
.attr("class", "grid_n");
svg.append("text")
.attr("x", offset_x + spacer * i + spacer / 1.5)
.attr("y", margin.top)
.attr("transform", "rotate(-" + gk + ", " + (offset_x + spacer * i + spacer / 1.5) + ", " + margin.top + ")")
.attr("class", "namen")
.text(namen[i]);
}
var g = svg.selectAll(".gs")
.data(parties)
.enter()
.append("g")
.attr("class", "gs")
.attr("transform", function(d) { return "translate(0, " + scale.y(d) + ")"; });
g.append("text")
.attr("x", 0)
.attr("y", scale.y.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("class", "parties")
.text(function(d) { return labels[d]; });
var gl = g.selectAll(".bars").data(laender).enter();
gl.append("rect")
.attr("x", function(d, i) { return offset_x + spacer * i; })
.attr("y", 0)
.attr("width", function(d) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig); })
.attr("height", scale.y.bandwidth())
.attr("class", "bars")
.style("fill", function() { var p = d3.select(this.parentNode).datum(); return color[p]; });
gl.append("text")
.attr("x", function(d, i) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig) + offset_x + spacer * i; })
.attr("y", scale.y.bandwidth() / 2)
.attr("dx", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "0.2em" : "-0.2em"; })
.attr("dy", "0.35em")
.attr("class", "result")
.style("text-anchor", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "start" : "end"; })
.style("fill", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "#000000" : "#ffffff"; })
.text(function(d) { var p = d3.select(this.parentNode).datum(); return percent.format(",.1%")(+d[p] / +d.gueltig); });
svg.selectAll(".gs").on("mouseover", function() { d3.select(this).selectAll(".result").style("visibility", "visible"); })
.on("mouseout", function() { d3.select(this).selectAll(".result").style("visibility", "hidden"); });
var add = svg.append("g").attr("id", "gemeinden").attr("transform", function() { return "translate(0, " + scale.y("gemeinden") + ")"; })
.on("mouseover", function() { d3.select(this).selectAll(".result").style("visibility", "visible"); })
.on("mouseout", function() { d3.select(this).selectAll(".result").style("visibility", "hidden"); });
add.append("text")
.attr("x", 0)
.attr("y", scale.y.bandwidth() / 2)
.attr("dy", "-0.7em")
.attr("class", "add")
.text("bisher");
add.append("text")
.attr("x", 0)
.attr("y", scale.y.bandwidth() / 2)
.attr("dy", "0.3em")
.attr("class", "add")
.text("ausgezählte");
add.append("text")
.attr("x", 0)
.attr("y", scale.y.bandwidth() / 2)
.attr("dy", "1.3em")
.attr("class", "add")
.text("Gemeinden");
add.selectAll(".gems")
.data(azg)
.enter()
.append("rect")
.attr("x", function(d, i) { return offset_x + spacer * i; })
.attr("y", 0)
.attr("width", function(d) { return scale.azg(d); })
.attr("height", scale.y.bandwidth())
.attr("class", "gems")
.style("fill", "#636363");
add.selectAll(".result")
.data(azg)
.enter()
.append("text")
.attr("x", function(d, i) { return scale.azg(d) + offset_x + spacer * i; })
.attr("y", scale.y.bandwidth() / 2)
.attr("dx", function(d) { return d < scale.result.domain()[1] - 0.2 ? "0.2em" : "-0.2em"; })
.attr("dy", "0.3em")
.attr("class", "result")
.style("fill", function(d) { return d < scale.result.domain()[1] - 0.2 ? "#000000" : "#ffffff"; })
.style("text-anchor", function(d) { return d < scale.result.domain()[1] - 0.2 ? "start" : "end"; })
.text(function(d) { return percent.format(",.1%")(d); });
}
function change(id)
{
d3.selectAll(".button").classed("pressed", false);
d3.select("#" + id).classed("pressed", true);
var g = svg.selectAll(".gs");
if (id == "share")
{
g.selectAll(".bars")
.transition()
.duration(1000)
.attr("width", function(d) { var p = d3.select(this.parentNode).datum(); return scale.share(+d[p] / +aut[0][p]); });
g.selectAll(".result")
.attr("x", function(d, i) { var p = d3.select(this.parentNode).datum(); return scale.share(+d[p] / +aut[0][p]) + offset_x + spacer * i; })
.attr("dx", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "0.2em" : "-0.2em"; })
.style("text-anchor", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "start" : "end"; })
.style("fill", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "#000000" : "#ffffff"; })
.text(function(d) { var p = d3.select(this.parentNode).datum(); return percent.format(",.1%")(+d[p] / +aut[0][p]); });
}
else
{
g.selectAll(".bars")
.transition()
.duration(1000)
.attr("width", function(d) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig); });
g.selectAll(".result")
.attr("x", function(d, i) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig) + offset_x + spacer * i; })
.attr("dx", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "0.2em" : "-0.2em"; })
.style("text-anchor", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "start" : "end"; })
.style("fill", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "#000000" : "#ffffff"; })
.text(function(d) { var p = d3.select(this.parentNode).datum(); return percent.format(",.1%")(+d[p] / +d.gueltig); });
}
}
function resize()
{
var id = d3.select("#buttons").select(".pressed").attr("id");
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) - parseInt(d3.select("#buttons").style("height"), 10);
var spacer = Math.floor((width - offset_x) / laender.length);
var gk = Math.atan((offset_y - margin.top) / (spacer / 1.5)) * 180 / Math.PI;
scale.result.range([0, spacer]);
scale.share.range([0, spacer]);
scale.azg.range([0, spacer - 1]);
scale.y.rangeRound([offset_y + margin.top, height - margin.bottom]);
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.selectAll(".grid_v, .grid_n, .namen").remove();
for (var i = 0; i < namen.length; i++)
{
svg.append("line")
.attr("x1", offset_x + spacer * i)
.attr("x2", offset_x + spacer * i)
.attr("y1", offset_y)
.attr("y2", height)
.attr("class", "grid_v");
svg.append("line")
.attr("x1", offset_x + spacer * i + spacer / 1.5)
.attr("x2", offset_x + spacer * i)
.attr("y1", margin.top)
.attr("y2", offset_y)
.attr("class", "grid_n");
svg.append("text")
.attr("x", offset_x + spacer * i + spacer / 1.5)
.attr("y", margin.top)
.attr("transform", "rotate(-" + gk + ", " + (offset_x + spacer * i + spacer / 1.5) + ", " + margin.top + ")")
.attr("class", "namen")
.text(namen[i]);
}
var g = svg.selectAll(".gs")
.attr("transform", function(d) { return "translate(0, " + scale.y(d) + ")"; });
g.selectAll(".parties")
.attr("y", scale.y.bandwidth() / 2);
if (id == "share")
{
g.selectAll(".bars")
.attr("x", function(d, i) { return offset_x + spacer * i; })
.attr("width", function(d) { var p = d3.select(this.parentNode).datum(); return scale.share(+d[p] / +aut[0][p]); })
.attr("height", scale.y.bandwidth());
g.selectAll(".result")
.attr("x", function(d, i) { var p = d3.select(this.parentNode).datum(); return scale.share(+d[p] / +aut[0][p]) + offset_x + spacer * i; })
.attr("y", scale.y.bandwidth() / 2)
.attr("dx", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "0.2em" : "-0.2em"; })
.style("text-anchor", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "start" : "end"; })
.style("fill", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +aut[0][p]) < 0.2 ? "#000000" : "#ffffff"; });
}
else
{
g.selectAll(".bars")
.attr("x", function(d, i) { return offset_x + spacer * i; })
.attr("width", function(d) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig); })
.attr("height", scale.y.bandwidth());
g.selectAll(".result")
.attr("x", function(d, i) { var p = d3.select(this.parentNode).datum(); return scale.result(+d[p] / +d.gueltig) + offset_x + spacer * i; })
.attr("y", scale.y.bandwidth() / 2)
.attr("dx", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "0.2em" : "-0.2em"; })
.style("text-anchor", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "start" : "end"; })
.style("fill", function(d) { var p = d3.select(this.parentNode).datum(); return (+d[p] / +d.gueltig) < 0.2 ? "#000000" : "#ffffff"; });
}
var add = svg.select("#gemeinden").attr("transform", function() { return "translate(0, " + scale.y("gemeinden") + ")"; });
add.selectAll(".add").attr("y", scale.y.bandwidth() / 2);
add.selectAll(".gems")
.attr("x", function(d, i) { return offset_x + spacer * i; })
.attr("width", function(d) { return scale.azg(d); })
.attr("height", scale.y.bandwidth());
add.selectAll(".result")
.attr("x", function(d, i) { return scale.azg(d) + offset_x + spacer * i; })
.attr("y", scale.y.bandwidth() / 2)
.attr("dx", function(d) { return d < scale.result.domain()[1] - 0.2 ? "0.2em" : "-0.2em"; })
.style("fill", function(d) { return d < scale.result.domain()[1] - 0.2 ? "#000000" : "#ffffff"; })
.style("text-anchor", function(d) { return d < scale.result.domain()[1] - 0.2 ? "start" : "end"; });
}
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js