D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
dyorama
Full window
Github gist
Version 3 : Top 20 french cities by natural disasters : type and number per year
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Stacked area chart</title> <script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script> <style type="text/css"> body { margin: 0; background-color: white; } #container { width: 900px; margin-left: 40px; margin-right: auto; margin-bottom: 50px; margin-top: 50px; padding-top: 20px; padding-left: 10px; padding-right: 30px; padding-bottom: 10px; background-color: white; box-shadow: 2px 2px 3px 3px #fcfcfc; border-width:1px; } h1 { font-size: 24px; margin: 0; } p { font-size: 14px; margin: 10px 0 0 0; } svg { background-color: white; } rect:hover { fill: #white; opacity: 0.4; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .x.axis text { font-family: helvetica; font-size: 12px; } .y.axis text { font-family: helvetica; font-size: 12px; } .legend text { font-family: helvetica; font-size: 12px; } </style> </head> <body> <div id="container"> </div> <script type="text/javascript"> //Set up stack method var stack = d3.layout.stack() .values(function(d) { return d.disaster; }); //.order("reverse"); //Width, height, padding var w = 900; var h = 550; var padding = [ 40, 20, 50, 100 ]; //Top, right, bottom, left //Set up date format function (année) var dateFormat = d3.time.format("%Y"); //Set up scales var xScale = d3.time.scale() .rangeRound([ padding[3], w - padding[1] ]); var yScale = d3.scale.linear() .range([ 0, h - padding[0] - padding[2] ]); //Configure axis generators var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") .ticks(33) .outerTickSize(0) .tickFormat(function(d) { return dateFormat(d); }); var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .ticks(12); //Configure area generator // var area = d3.svg.area() // .x(function(d) { // return xScale(dateFormat.parse(d.x)); // }) // .y0(function(d) { // return yScale(d.y0); //Updated // }) // .y1(function(d) { // return yScale(d.y0 + d.y); //Updated // }); //Easy colors accessible via a 10-step ordinal scale var color = d3.scale.ordinal() .range(["#009ACD", "#2ADF82", "#FFC115", "#006FCD", "FF3E0E"]); //Create the empty SVG image var svg = d3.select("#container") .append("svg") .attr("width", w) .attr("height", h); //Load data d3.csv("stackdisaster.csv", function(data) { //Uncomment to log the newly loaded data to the console //console.log(data); //Data is loaded in, but we need to restructure it. //Remember, each line requires an array of x/y pairs; //that is, an array of arrays, like so: // // [ [x: 1, y: 1], [x: 2, y: 2], [x: 3, y: 3] ] // //Our x value will be the year, and y will be the amount //of CO2. We also need to know which nom belongs to //each line, so we will build an array of objects that is //structured like this: // /* [ { nom: "Australia", disaster: [ { x: "1961", y: 90589.568 }, { x: "1962", y: 94912.961 }, { x: "1963", y: 101029.517 }, … ] }, { nom: "Bermuda", disaster: [ { x: "1961", y: 176.016 }, { x: "1962", y: 157.681 }, { x: "1963", y: 150.347 }, … ] }, … ] */ // //Note that this is an array of objects. Each object //contains two values, 'nom' and 'disaster'. //The 'disaster' value is itself an array, containing //more objects, each one holding x and y values. // //The x (year) values have to be strings in this case, //because the date format function expects a string //to parse into a Date object. //New array with all the année, for referencing later var année = ["1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016"]; //Create a new, empty array to hold ur restructured dataset var dataset = []; //Loop once for each row in data for (var i = 0; i < data.length; i++) { //Create new object with this nom's name and empty array dataset[i] = { nom: data[i].disaster, disaster: [] }; //Loop through all the année for (var j = 0; j < année.length; j++) { //Default value, used in case no value is present var amount = null; // If value is not empty if (data[i][année[j]]) { amount = +data[i][année[j]]; } //Add a new object to the disaster data array //for this nom dataset[i].disaster.push({ x: année[j], y: amount }); } } //Stack the data! stack(dataset); //Uncomment to log the original data to the console // console.log(data); //Uncomment to log the newly restructured dataset to the console console.log(dataset); //Now that the data is ready, we can check its //min and max values to set our scales' domains! xScale.domain([ d3.min(année, function(d) { return dateFormat.parse(d); }), d3.max(année, function(d) { return dateFormat.parse(d); }) ]); // Need to recalcluate the max value for yScale //differently, now that everything is stacked. //Loop once for each year, and get the total value //of CO2 for that year. var totals = []; for (i = 0; i < année.length; i++) { totals[i] = 0; for (j = 0; j < dataset.length; j++) { totals[i] += dataset[j].disaster[i].y; } } yScale.domain([ 0, d3.max(totals) ]); //Areas // //Now that we are creating multiple paths, we can use the //selectAll/data/enter/append pattern to generate as many //as needed. //Make a path for each nom // var paths = svg.selectAll("path") // .data(dataset) // .enter() // .append("path") // .attr("class", "area") // .attr("d", function(d) { // //Calculate path based on only d.disaster array, // //not all of d (which would include the nom name) // return area(d.disaster); // }) // .attr("stroke", "none") // .attr("fill", function(d, i) { // return color(i); // }); //Append a title with the nom name (so we get easy tooltips) // paths.append("title") // .text(function(d) { // return d.nom; // }); // Add a group for each row of data var groups = svg.selectAll("g") .data(dataset) .enter() .append("g") .style("fill", function(d, i) { return color(i); }); // Add a rect for each data value var rects = groups.selectAll("rect") .data(function(d) { return d.disaster; }) .enter() .append("rect") //+ 5 permet de pousser les rectangles de 5 vers la droite .attr("x", function(d) { return xScale(dateFormat.parse(d.x)) + 5; }) .attr("width", 15) .attr("y", function(d) { //return yScale(d.y); //Flip the math! xxx return h - yScale(d.y0) - yScale(d.y) - padding[2]; //Flip the math! }) .attr("height", function(d) { return yScale(d.y); }); //Les titres doivent être donnés au groupe groups.append("title") .text(function(d) { return d.year + " : " + d.nom + " " + d.disaster; }); //Create axes svg.append("g") .attr("class", "x axis") //pousser l'axe des abcsisses de 12 pixels vers la droite .attr("transform", "translate(12," + (h - padding[2]) + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dy", ".-20em") .attr("dx", "-8") .attr("transform", function(d) {return "rotate(-70)"}); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + padding[3] + "," + padding[0] + ")") .call(yAxis); svg.append("text") .attr ("x", 120) .attr ("y", (padding[0] / 3)) .style("font-size", "14px") .style("font-family", "Helvetica") .style("font-weight", "none") .style("font-style", "italic") .text("Number and type of natural disasters per year "); var legend = svg.selectAll(".legend") .data(color.domain().slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 25 + ")"; }); legend.append("rect") .attr("x", w - 150) .attr("width", 15) .attr("height", 15) .style("fill", color); legend.append("text") .attr("x", w - 130) .attr("y", 9) .attr("dy", ".35em") .text(function(d, i) { switch (i) { case 0: return "Earthquake"; case 1: return "Waves"; case 2: return "Drough"; case 3: return "Landslide"; case 4: return "Flooding"; } }); }); </script> </body> </html>
https://d3js.org/d3.v3.min.js