D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
Federicopvs
Full window
Github gist
turinBudgetNew
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div id="container"> <h1>Il budget del comune di Torino</h1> <form> <label><input id="change2014" type="radio" name="dataset" value="val2014" checked="checked" /> 2014</label> <label><input id="change2013" type="radio" name="dataset" value="val2013" /> 2013</label> </form> <p>Totale: <span id="total">xx</span> € - Procapite: <span id="perCapita">xx</span> €</p> <div id="containerViz"> <div id="tooltip" class="hidden"> <p> <strong><span id="voce"></span></strong> </p> <p> <span class="tooltipTitle">Importo</span><br><span id="value"></span> </p> <p> <span class="tooltipTitle">Percentuale</span><br><span id="percent"></span> </p> <p> <span class="tooltipTitle">Procapite</span><br><span id="procapite"></span> </p> </div> <script type="text/javascript"> //LOAD DATA d3.json("data.json", function(error, json) { if (error) { console.log(error); } else { console.log(json); dataset=json; drawInner(); draw(); interactivity (); change(); colorRanges(); } }) //LAYOUT var dataset; var h = 500; var w = 500; var padding = 5; var outerRadius = (w / 2)-padding; var innerRadius = w / 3; var innerRadiusInner = w / 4; var greenRange = ["rgb(116,196,118)", "rgb(0,68,27)"]; var redRange = ["rgb(203,24,29)", "rgb(103,0,13)"]; var blueRange = ["rgb(33,113,181)", "rgb(8,48,107)"]; var colorInner = d3.scale.ordinal() .domain(["funzioni", "rimborso prestiti", "altro"]) .range(["rgb(35,139,69)", "rgb(165,15,21)" , "rgb(8,81,156)"]); var arc = d3.svg.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); var arcInner = d3.svg.arc() .innerRadius(innerRadiusInner) .outerRadius(innerRadius); var pie = d3.layout.pie() .value(function(d) { return d.val2014; }) .sort(null) .padAngle(.001); var pieInner = d3.layout.pie() .value(function(d) { return d.values; }) .sort(null) .padAngle(.001); function arcTween(a) { var i = d3.interpolate(this._current, a); this._current = i(0); return function(t) { return arc(i(t)); }; } function arcTweenInner(a) { var i = d3.interpolate(this._current, a); this._current = i(0); return function(t) { return arcInner(i(t)); }; } function key(d) { return d.data.key; } // Find the element in data0 that joins the highest preceding element in data1. function findPreceding(i, data0, data1, key) { var m = data0.length; while (--i >= 0) { var k = key(data1[i]); for (var j = 0; j < m; ++j) { if (key(data0[j]) === k) return data0[j]; } } } // Find the element in data0 that joins the lowest following element in data1. function findFollowing(i, data0, data1, key) { var n = data1.length, m = data0.length; while (++i < n) { var k = key(data1[i]); for (var j = 0; j < m; ++j) { if (key(data0[j]) === k) return data0[j]; } } } function findNeighborArc(i, data0, data1, key) { var d; return (d = findPreceding(i, data0, data1, key)) ? {startAngle: d.endAngle, endAngle: d.endAngle} : (d = findFollowing(i, data0, data1, key)) ? {startAngle: d.startAngle, endAngle: d.startAngle} : null; } //Add commas every three digits (tooltip) function commafy( num ) { var str = num.toString().split('.'); if (str[0].length >= 5) { str[0] = str[0].replace(/(\d)(?=(\d{3})+$)/g, "$1'"); } if (str[1] && str[1].length >= 5) { str[1] = str[1].replace(/(\d{3})/g, '$1 '); } return str.join('.'); } function colorRanges () { countFunzioni=0; dataset.forEach (function (d) {if (d.categoria=="funzioni") { countFunzioni += 1; d.catIndex = countFunzioni;}}) countRimborso=0; dataset.forEach (function (d) {if (d.categoria=="rimborso prestiti") { countRimborso += 1; d.catIndex = countRimborso;}}) countAltro=0; dataset.forEach (function (d) {if (d.categoria=="altro") { countAltro += 1; d.catIndex = countAltro;}}) colorFunzioni = d3.scale.linear() .domain([0, countFunzioni]) .range(greenRange); colorRimborso = d3.scale.linear() .domain([0, countRimborso]) .range(redRange); colorAltro = d3.scale.linear() .domain([0, countAltro]) .range(blueRange); } function coloring (d, i) { colorRanges(); colorMap = { "funzioni": colorFunzioni, "altro": colorAltro, "rimborso prestiti": colorRimborso } var scale = colorMap[d.data.categoria]; if (scale) return scale(d.data.catIndex); } function drawInner () { nestCategoria = d3.nest() .key(function (d) {return d.categoria;}) .rollup(function (d) {return d3.sum(d, function (g) {return g.val2014;});}) .entries(dataset) chartInner = d3.select("#containerViz") .append("svg") .attr("id", "visualizationInner") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")"); pathInner = chartInner.datum(nestCategoria).selectAll("path") .data(pieInner(nestCategoria)) .enter() .append("path") .attr("fill", function(d, i) { return colorInner(i); }) .style("fill-opacity", 0.8) .attr("d", arcInner) .each(function (d) { this._current = d; }); } function draw () { chart = d3.select("#visualizationInner") .append("svg") .attr("id", "visualization") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")"); path = chart.datum(dataset).selectAll("path") .data(pie(dataset)) .enter() .append("path") .attr("fill", coloring) .style("fill-opacity", 0.8) .attr("d", arc) .each(function (d) { this._current = d; }); var total = d3.sum(dataset.map(function(d) { return d.val2014;})); total = commafy(total); d3.select("#total").text(function () {return total;}) } function interactivity () { d3.selectAll("path").on("mouseover", function (d) { var total = d3.sum(dataset.map(function(d) { return d.val2014;})); var percent = Math.round(1000 * d.value / total) / 10; var valueNew = d.value; valueNew = commafy(valueNew); //highlight d3.select(this) .style("fill-opacity", 1) //update tooltip text d3.select("#tooltip") .select("#voce") .text(d.data.key); d3.select("#tooltip") .select("#value") .text(valueNew + " €"); d3.select("#tooltip") .select("#percent") .text(percent + " %"); //display tooltip d3.select("#tooltip") //.style("left", w/2 + "px") .style("top", h/2 + "px") .classed("hidden", false) }) d3.selectAll("path").on("mouseout", function () { //remove highlihgt d3.select(this) .style("fill-opacity", 0.8) //hide tooltip d3.select("#tooltip") .classed("hidden", true) }) d3.selectAll("path").on("click", function (d) { //update tooltip title d3.select("#descrTitle") .text(d.data.descrTitle) //update tooltip text d3.select("#descrText") .html(d.data.descrText) //update tooltip image descrImg = d3.select("#descrImg"); descrImg.select("svg").remove(); //removes previous image d3.selectAll("path").attr("stroke-width", 0); //remove previous stroke descrImgURI = d.data.descrImg; fillColor = d3.select(this).attr("fill"); //extract color d3.select(this).attr("stroke", fillColor); d3.select(this).attr("stroke-width", 3); d3.xml(descrImgURI, "image/svg+xml", function(error, xml) { if (error) throw error; var svg= xml.documentElement; descrImg.node().appendChild(svg); var a = document.getElementById("Ebene_1"); var b = a.getElementsByTagName("circle")[0]; var c = a.getElementsByTagName("path"); d3.select(b).attr("fill", fillColor); d3.selectAll(c).attr("fill", "white"); }); }) } function change() { function newPie () { // path.data(pie); // compute the new angles // path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs var data0 = path.data(); path = path.data(data1, key); path.enter().append("path") .each(function(d, i) { this._current = findNeighborArc(i, data0, data1, key) || d; }) .attr("fill", coloring) path.exit() .datum(function(d, i) { return findNeighborArc(i, data1, data0, key) || d; }) .transition() .duration(750) .attrTween("d", arcTween) .remove(); path.transition() .duration(750) .attrTween("d", arcTween); } function newPieInner() { pathInner.data(pieInner(nestCategoria)); // compute the new angles pathInner.transition().duration(750).attrTween("d", arcTweenInner); // redraw the arcs } d3.select("#change2013").on("click", function() { //change total var total = d3.sum(dataset.map(function(d) { return d.val2013;})); total = commafy(total); d3.select("#total").text(function () {return total;}) data1 = pie.value(function (d) { return d.val2013; }); // change the value function newPie(); nestCategoria = d3.nest() .key(function (d) {return d.categoria;}) .rollup(function (d) {return d3.sum(d, function (g) {return g.val2013;});}) .entries(dataset) newPieInner(); }); d3.select("#change2014").on("click", function() { //change total var total = d3.sum(dataset.map(function(d) { return d.val2014;})); total = commafy(total); d3.select("#total").text(function () {return total;}) data1 = pie.value(function (d) { return d.val2014; }); // change the value function newPie(); nestCategoria = d3.nest() .key(function (d) {return d.categoria;}) .rollup(function (d) {return d3.sum(d, function (g) {return g.val2014;});}) .entries(dataset) newPieInner(); }); } </script> </div> <!-- containerViz --> <div class="description hidden" id="funzioni"> <span id="descrImg"></span> <p><strong><span id="descrTitle">Istruzioni</strong></span></p> <p><span id="descrText">Clicca sulla fetta di torta per ottenere maggiori informazioni riguardo alla funzione governativa.</span></p> </div> </div> <!-- container --> </body> </html>
https://d3js.org/d3.v3.min.js