D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
ginseng666
Full window
Github gist
offene wahlen: darstellung länder
<!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>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