D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
ginseng666
Full window
Github gist
offene wahlen: darstellung urbanisierung
<!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>Stadt-Land/Urbanisierung</title> </head> <body> <div id="container"> <div class="desc">Ein möglicher Unterschied zwischen Stadt und Land in Österreich lässt sich anhand des Urbanisierungsgrades überprüfen: Die Einteilung basiert auf den Kategorien der Europäischen Kommission, die zwei Faktoren berücksichtigt, Bevölkerungszahl pro km² und Bevölkerungszahl der Gemeinde insgesamt. Sie teilt das Gebiet in Rasterzellen, die jeweils einen km² groß sind, darauf bauen die Definitionen auf: <ul><li>ländlich: weniger als 50 Prozent der Bevölkerung leben in einer Rasterzelle mit 300 EinwohnerInnen, Gesamtbevölkerung unter 5.000</li> <li>mittel: mehr als 50 Prozent der Bevölkerung leben in einer Rasterzelle mit mehr als 300 EinwohnerInnen, aber weniger als 50 Prozent wohnen in einer urbanen Rasterzelle (siehe unten); Gesamtbevölkerung mindestens 5.000</li> <li>städtisch: mehr als 50 Prozent der Bevölkerung leben in einem Raster mit mehr als 1.500 Menschen, Gesamtbevölkerung mindestens 50.000</li></ul> Gut 80 Prozent der österreichischen Gemeinden gelten in dieser Logik als "ländlich", es gibt insgesamt nur sechs städtische Regionen: Wien, Graz, Linz, Salzburg, Innsbruck und Klagenfurt.<br><br> Die erste Grafik zeigt den <span style="color: #e34a33; text-decoration: underline">Auszählungsgrad</span> (=Summe der Wahlberechtigten in den bis jetzt ausgezählten Gemeinden) für jede der drei Kategorien sowie insgesamt, die <span style="color: #fee8c8; text-decoration: underline">Balken im Hintergrund</span> stehen für den Anteil der Kategorie an allen Wahlberechtigten (also z.B. der ländlichen Regionen an ganz Österreich). </div> <div id="azg"> </div> <div class="desc"> Die zweite Grafik zeigt das Ergebnis der Parteien in ländlichen, mittleren und städtischen Gemeinden im Verhältnis zum Gesamtergebnis (jeweils ohne Wahlkarten). </div> <div id="chart"> <div id="legend"> </div> </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.selectAll(".desc").style("height"), 10); //TODO: Mindestmaße festlegen if (height < 400) height = 400; var parties = ["spoe", "oevp", "fpoe", "gruene", "neos", "frank", "kpoe"]; //sollte aus der db kommen var labels = {"spoe": "SPÖ", "oevp": "ÖVP", "fpoe": "FPÖ", "gruene": "GRÜNE", "neos": "NEOS", "frank": "FRANK", "kpoe": "KPÖ"}; var color = {"oevp": "#191919", "spoe": "#ca5670", "fpoe": "#638ccc", "gruene": "#72a555", "kpoe": "#9F000F", "neos": "#F52887", "frank": "#E9AB17", "bzoe": "#F87431", "tie": "grey"}; var urbanisierung, gemeinden; var wbr = {"total": 0, "land": 0, "mittel": 0, "stadt": 0}; //wahlberechtigte für den auszählungsgrad var current = {}; //auszählungsgrade var gueltig = {"total": 0, "land": 0, "mittel": 0, "stadt": 0}; //gültige stimmen für das ergebnis var results = []; var offset_x = 75; //abstand balken links; //TODO: bei der scale überlegen, ob 100% oder nicht //azg: offset rechts zwecks beschriftung? var scale = {"result": d3.scaleLinear().domain([0, 1]).range([0, width - offset_x]), "y": d3.scaleBand().domain(parties).rangeRound([margin.top, height - margin.bottom]).paddingOuter(0).paddingInner(0.3), "classes": d3.scaleBand().domain(d3.range(3)).paddingOuter(0.2).paddingInner(0.1), "azg": d3.scaleLinear().range([0, width - offset_x - 15]), "azg_y": d3.scaleBand().rangeRound([0, 200]).paddingOuter(0).paddingInner(0.1)}; scale.classes.rangeRound([0, scale.y.bandwidth()]); 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 legend = d3.select("#legend") .append("svg") .attr("width", scale.classes.bandwidth() * 3 + 60) .attr("height", scale.y.bandwidth() + 15) .attr("id", "svg_legend"); var azg = d3.select("#azg") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", 200 + margin.top + margin.bottom) //variable höhe? .attr("id", "svg_azg") .append("g") .attr("transform", "translate(" + margin.left + ", " + margin.top + ")"); //TODO: ein gemeinsames resize? window.onresize = resize; var q = d3.queue(); q.defer(d3.tsv, "daten_2013in2017.txt"); q.defer(d3.tsv, "urbanisierung.txt"); q.awaitAll(function(error) { if (!error) { gemeinden = arguments[1][0].filter(function(d) { return (d.gkz.slice(-2) != "00" && d.gkz.slice(-2) != "99" && d.gkz.slice(0, 2) != "G9") || (d.gkz == "G90001"); }); urbanisierung = d3.nest().key(function(d) { return "G" + d.gkz; }).object(arguments[1][1]); gemeinden.forEach(function(d) { d.urbanisierung = urbanisierung[d.gkz][0].urbanisierung; }); wbr.total = +arguments[1][0].filter(function(d) { return d.gkz == "G00000"; })[0].wahlberechtigte; wbr.stadt = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d.wahlberechtigte; }); wbr.mittel = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d.wahlberechtigte; }); wbr.land = wbr.total - wbr.stadt - wbr.mittel; //fiktive auszählungsgrade current.stadt = Math.round(wbr.stadt * Math.random()); current.mittel = Math.round(wbr.mittel * Math.random()); current.land = Math.round(wbr.land * Math.random()); current.total = current.stadt + current.mittel + current.land; scale.azg.domain([0, wbr.total]); gueltig.total = +arguments[1][0].filter(function(d) { return d.gkz == "G00000"; })[0].gueltig; gueltig.stadt = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d.gueltig; }); gueltig.mittel = d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d.gueltig; }); gueltig.land = gueltig.total - gueltig.stadt - gueltig.mittel; for (var i = 0, len = parties.length; i < len; i++) { var p = parties[i]; var obj = {}; obj.p = p; obj.total = d3.sum(gemeinden, function(d) { return +d[p]; }) / gueltig.total; obj.classes = []; obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "3"; }), function(d) { return d[p]; }) / gueltig.land); obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "2"; }), function(d) { return d[p]; }) / gueltig.mittel); obj.classes.push(d3.sum(gemeinden.filter(function(d) { return d.urbanisierung == "1"; }), function(d) { return d[p]; }) / gueltig.stadt); results.push(obj); } draw(); } }); function draw() { var azgs = ["total", "land", "mittel", "stadt"]; var classes = ["ländlich", "mittel", "städtisch"]; scale.azg_y.domain(azgs); azg.selectAll(".bg_rect") .data(azgs) .enter() .append("rect") .attr("x", offset_x) .attr("y", function(d) { return scale.azg_y(d); }) .attr("width", function(d) { return scale.azg(wbr[d]); }) .attr("height", scale.azg_y.bandwidth()) .attr("class", "bg_rect") .style("fill", "#ece7f2"); azg.selectAll(".azg_rect") .data(azgs) .enter() .append("rect") .attr("x", offset_x) .attr("y", function(d) { return scale.azg_y(d) + 10; }) .attr("width", function(d) { return scale.azg(current[d]); }) .attr("height", scale.azg_y.bandwidth() - 20) .attr("class", "azg_rect") .style("fill", "#2b8cbe"); azg.selectAll(".parties") .data(azgs) .enter() .append("text") .attr("x", 0) .attr("y", function(d, i) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; }) .attr("dy", "0.35em") .text(function(d, i) { return ["gesamt"].concat(classes)[i]; }); azg.selectAll(".values") .data(azgs) .enter() .append("text") .attr("x", function(d) { return scale.azg(wbr[d]) + offset_x + 2; }) .attr("y", function(d, i) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; }) .attr("dy", "0.35em") .attr("class", "values") .text(function(d) { return percent.format(",.0%")(current[d] / wbr[d]); }); legend.append("line") .attr("x1", 60 + scale.classes.bandwidth() * 1.5) .attr("x2", 60 + scale.classes.bandwidth() * 1.5) .attr("y1", 15) .attr("y2", scale.y.bandwidth() + 15) .style("stroke", color.spoe); legend.append("text") .attr("x", 60 + scale.classes.bandwidth() * 1.5) .attr("y", 12) .attr("class", "legtext") .style("text-anchor", "middle") .text("gesamt"); for (var i = 0; i < 3; i++) { legend.append("text") .attr("x", 0) .attr("y", scale.classes(i) + scale.classes.bandwidth() / 2 + 15) .attr("dy", "0.35em") .attr("class", "legtext") .text(classes[i]); legend.append("rect") .attr("x", 60) .attr("y", scale.classes(i) + 15) .attr("width", scale.classes.bandwidth() * 3) .attr("height", scale.classes.bandwidth()) .style("fill", color.spoe) .style("fill-opacity", 0.3 + 0.3 * i); } var g = svg.selectAll(".gs") .data(results) .enter() .append("g") .attr("class", "gs") .attr("transform", function(d) { return "translate(0, " + scale.y(d.p) + ")"; }); g.append("text") .attr("x", 0) .attr("y", scale.classes.bandwidth() * 2) .attr("class", "parties") .attr("dy", "0.3em") .text(function(d) { return labels[d.p]; }); //TODO //Gesamt-Wert = nur Gemeinden, oder inkl. Wahlkarten? Am Wahltag egal? g.append("line") .attr("x1", function(d) { return offset_x + scale.result(d.total); }) .attr("x2", function(d) { return offset_x + scale.result(d.total); }) .attr("y1", 0) .attr("y2", scale.y.bandwidth()) .attr("class", "grid") .style("stroke", function(d) { return color[d.p]; }); g.selectAll(".bars") .data(function(d) { return d.classes; }) .enter() .append("rect") .attr("x", offset_x) .attr("y", function(d, i) { return scale.classes(i); }) .attr("width", function(d) { return scale.result(d); }) .attr("height", scale.classes.bandwidth()) .attr("class", "bars") .style("fill", function(d) { var p = d3.select(this.parentNode).datum().p; return color[p]; }) .style("fill-opacity", function(d, i) { return 0.3 + 0.3 * i; }); g.selectAll(".result") .data(function(d) { return d.classes; }) .enter() .append("text") .attr("x", function(d) { return offset_x + scale.result(d) + 4; }) .attr("y", function(d, i) { return scale.classes(i) + scale.classes.bandwidth() / 2; }) .attr("dy", "0.35em") .attr("class", "result") .text(function(d) { return percent.format(",.1%")(d); }); } function resize() { width = parseInt(d3.select("#chart").style("width"), 10) - margin.left - margin.right; height = window.innerHeight - margin.top - margin.bottom - 40 - parseInt(d3.selectAll(".desc").style("height"), 10); if (height < 400) height = 400; scale.result.range([0, width - offset_x]); scale.y.rangeRound([margin.top, height - margin.bottom]); scale.classes.rangeRound([0, scale.y.bandwidth()]); scale.azg.range([0, width - offset_x - 15]); scale.azg_y.rangeRound([0, 200]).paddingOuter(0).paddingInner(0.1); 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 + ")"); d3.select("#svg_azg") .attr("width", width + margin.left + margin.right) .select("g") .attr("transform", "translate(" + margin.left + ", " + margin.top + ")"); azg.selectAll(".bg_rect") .attr("y", function(d) { return scale.azg_y(d); }) .attr("width", function(d) { return scale.azg(wbr[d]); }) .attr("height", scale.azg_y.bandwidth()); azg.selectAll(".azg_rect") .attr("y", function(d) { return scale.azg_y(d) + 10; }) .attr("width", function(d) { return scale.azg(current[d]); }) .attr("height", scale.azg_y.bandwidth() - 20); azg.selectAll(".parties") .attr("y", function(d) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; }) azg.selectAll(".values") .attr("x", function(d) { return scale.azg(wbr[d]) + offset_x + 2; }) .attr("y", function(d) { return scale.azg_y(d) + scale.azg_y.bandwidth() / 2; }); var g = svg.selectAll(".gs"); g.attr("transform", function(d) { return "translate(0, " + scale.y(d.p) + ")"; }); g.selectAll(".parties") .attr("y", scale.classes.bandwidth() * 2); g.selectAll(".grid") .attr("x1", function(d) { return offset_x + scale.result(d.total); }) .attr("x2", function(d) { return offset_x + scale.result(d.total); }) .attr("y1", 0) .attr("y2", scale.y.bandwidth()); g.selectAll(".bars") .attr("y", function(d, i) { return scale.classes(i); }) .attr("width", function(d) { return scale.result(d); }) .attr("height", scale.classes.bandwidth()); g.selectAll(".result") .attr("x", function(d) { return offset_x + scale.result(d) + 4; }) .attr("y", function(d, i) { return scale.classes(i) + scale.classes.bandwidth() / 2; }); } </script> </body> </html>
https://d3js.org/d3.v4.min.js