D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
hichamelhady
Full window
Github gist
finl prod
Built with
blockbuilder.org
<!DOCTYPE html> <style> .axis .domain { display: none; } </style> <body> <div> <form> <label><input type="radio" name="mode" value="stacked" checked> Stacked</label> <label><input type="radio" name="mode" value="grouped"> Grouped</label> </form> <div id="diagprod" style="background-color: snow; display: inline-block;border: solid black 2px;"> </div> </div> <script src="https://d3js.org/d3.v4.min.js"></script> <script> // References : --> Mainly inspired by https://bl.ocks.org/mbostock/3943967 (Mike Bostock’s Block 3943967) var margin3 = {top: 15, right: 19, bottom: 30, left: 50}, width = 865 - margin3.left - margin3.right, height = 500 - margin3.top - margin3.bottom; // Scale definition var x = d3.scaleBand() .range([0, width]) .padding(0.4); var x1 = d3.scaleBand() .padding(0.1); var yBar = d3.scaleLinear() .range([height, 0]); var yStack = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal() .domain(["Photovoltaïque","Eolien","Cogénération","Hydraulique", "Autres"]) // Defined here, doesn't work into csv loop... .range(["blue", "orange", "green", "purple", "brown"]); // Axis (Pre)definition var xPreAxis = d3.axisBottom() .scale(x) .tickSize(0); var yPreAxis = d3.axisLeft(yStack); // Graphical environment var svgp = d3.select("#diagprod").append("svg") .attr("width", width + margin3.left + margin3.right) .attr("height", height + margin3.top + margin3.bottom); // Group for all plots var g = svgp.append("g") .attr("transform", "translate(" + margin3.left + "," + margin3.top + ")"); d3.csv("stocks.csv", function(data) { //**************************************************// // Data Preprocessing // //**************************************************// // Parse time var parseTime = d3.timeParse("%Y"); var formatTime = d3.timeFormat("%Y"); // Nest Data by year var nest_by_year = d3.nest() .key(function(d) {return formatTime(parseTime(d.date)); }) .entries(data); var transitional_data = []; nest_by_year.forEach(function(KeyYear) { // Nest data by symbol ("MSFT","AMZN","IBM", "AAPL") var nest_by_symbol = d3.nest() .key(function(d) {return d.symbol; }) .rollup(function(v) {return d3.mean(v,function(d) {return d.price; })}) .object(KeyYear.values); transitional_data.push({ key: +KeyYear.key, values: nest_by_symbol }); }); var final_data = transitional_data.map(function(d) { var merged = { year: d.key }; // Copy each key-val pair of d.values into merged Object.keys(d.values).forEach(function(key) { merged[key] = d.values[key]; }); return merged; }); // Get names and update scales var companiesNames = d3.keys(final_data[0]).slice(1); var totals = []; final_data.forEach(function(d){ totals.push(d3.sum(companiesNames, function(key) {return d[key]; })) }); x.domain(final_data.map(function(d) {return d.year; })); x1.domain(companiesNames).range([0, x.bandwidth()]); yBar.domain([0, d3.max(final_data, function(d) {return d3.max(companiesNames, function(key) {return d[key]; }); })]); yStack.domain([0, d3.max(totals)]); var group = g .selectAll("g") .data(d3.stack().keys(companiesNames)(final_data)) .enter().append("g") .attr("fill", function(d) { return color(d.key); }); var rect = group.selectAll("rect") .data(function(d) {return d; }) .enter().append("rect") .attr("x", function(d) {return x(d.data.year); }) .attr("y", function(d) {return yStack(d[1]); }) .attr("height", function(d) {return yStack(d[0]) - yStack(d[1]); }) .attr("width", x.bandwidth()); // Axis creation var xAxis = g.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xPreAxis); var yAxis = g.append("g") .attr("class", "y axis") .style('opacity','1') .attr("transform", "translate(20,0)") .call(yPreAxis) .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .style('font-weight','bold'); //**************************************************// // Transitions // //**************************************************// d3.selectAll("input") .on("change", changed); function changed() { if (this.value === "grouped") transitionGroupedChart(); else transitionStackedChart(); } function transitionGroupedChart() { rect .transition().duration(750) .attr("width", x1.bandwidth()) .transition().duration(1200) .attr("x", function(d,i) {return x(d.data.year) + x1(this.parentNode.__data__.key)}) .transition().duration(1200) .attr("y", function(d) {return yBar(d[1] - d[0]); }) .attr("height", function(d) {return yBar(0) - yBar(d[1]-d[0]); }); yAxis .transition() .call(d3.axisLeft(yBar)); }; function transitionStackedChart() { rect .transition().duration(1200) .attr("y", function(d) {return yStack(d[1] - d[0]); }) .attr("height", function(d) {return yStack(d[0]) - yStack(d[1]); }) .transition().duration(1200) .attr("y", function(d) {return yStack(d[1]); }) .transition().duration(750) .attr("x", function(d) {return x(d.data.year); }) .attr("width", x.bandwidth()); yAxis .transition() .call(d3.axisLeft(yStack)); }; // End of data processing }); //**************************************************// // Legend // //**************************************************// var legend = svgp.selectAll(".legend") .data(color.domain().reverse()) .enter() .append("g") .attr("class", "legend") .attr("transform", function(d,i) { return "translate(-800," + (i+1)* 25 + ")"; }) .style("opacity","1"); svgp.append("text") .attr("x", (width / 3.)) .attr("y", 0 + 2.5*(margin3.top)) .style("font-size", "30px") .style("text-decoration", "underline") .text("Energie annuelle produite en MWh"); legend.append("rect") .attr("x", width +100) .attr("width", 18) .attr("height", 18) .style("fill", function(d) { return color(d); }); legend.append("text") .attr("x", width +210) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) {return d; }); </script>
https://d3js.org/d3.v4.min.js