D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
Rade-Mathis
Full window
Github gist
TP3-p3-5
Built with
blockbuilder.org
Etapes de fabrication :
TP3-p1
TP3-p3-1
TP3-p3-2
TP3-p3-3
TP3-p3-4
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } svg { font: 10px sans-serif; } .line { /* useless here */ fill: none; stroke: black; stroke-width: 2.5px; } </style> </head> <body> <script> /* TODO : reindenter tout ca */// (by software) var margin = {top: 20, right: 40, bottom: 20, left: 100}; var width = 760 - margin.left - margin.right; var height = 300 - margin.top - margin.bottom; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // See formats https://bl.ocks.org/zanarmstrong/raw/05c1e95bf7aa16c4768e/ // Data sample {"name": "G", "value": 10, "date": "2016-07"} var parseDate = d3.timeParse("%b %Y"); var displayDate = d3.timeFormat("%y"); var displayValue = d3.format(",.0f"); // Ordinal scale var x = d3.scaleTime() .range([0, width]); // Linear scale var y = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal(d3.schemeCategory10); /* Fonctions dessineuses de formes. */ var line = d3.area() .curve(d3.curveBasis) .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.price - 1) ; }) .y1(function(d) { return y(d.price + 1) ; }); var area = d3.area() .curve(d3.curveBasis) .x(function(d) { return x(d.date); }) .y0(height) .y1(function(d) { return y(d.price); }); var separated_area = d3.area() .curve(d3.curveBasis) .x (function (d) { return x (d.date) ; }) .y0 (function (d) { return y (d.base) ; }) .y1 (function (d) { return y (d.price_on_base) ; }); var stacked_area = d3.area() .curve(d3.curveBasis) .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.sum_others); }) .y1(function(d) { return y(d.price_on_others); }); var centered_area = d3.area() .curve(d3.curveBasis) .x(function(d) { return x(d.date); }) .y0(function(d) { return y(d.sum_others_centered); }) .y1(function(d) { return y(d.price_on_others_centered); }); var g = svg.append("g") ; d3.text( "https://gist.githubusercontent.com/mbostock/1256572/raw/44c086a6019de56dce35a47197a19468b3e4ad57/stocks.csv", function (err,rawData) { var dsv = d3.dsvFormat (',') ; var data = dsv.parse (rawData) ; data.forEach(function(d) { d.price = +d.price; d.date = parseDate(d.date); }); var n_data = d3.nest () .key (function (d) { return d.symbol ; }) .entries (data) ; /* Du gros JS pour tirer des donnees */ // stacked et centered : for (i = 0; i < n_data.length; ++i) { for (j = 0; j < n_data[i].values.length; ++j) { var elem = n_data[i].values[j] ; elem.sum_others = 0 ; for (k = i + 1; k < n_data.length; ++k) { elem.sum_others += n_data[k].values[j].price ; } elem.price_on_others = elem.price + elem.sum_others ; } } var maxY = d3.max(data, function(d) { return d.price_on_others; }) ; x.domain(d3.extent(data, function(d) { return d.date; })); // centered : for (i = 0; i < n_data[0].values.length; ++i) { var blank_under = (maxY - n_data[0].values[i].price_on_others) / 2 ; for (j = 0; j < n_data.length; ++j) { var elem = n_data[j].values[i] ; elem.price_on_others_centered = elem.price_on_others + blank_under ; elem.sum_others_centered = elem.sum_others + blank_under ; } } // separated : for (i = 0; i < n_data.length; ++i) { n_data[i].max_price = d3.max(n_data[i].values, function (d) { return d.price ; }) ; } var max_max_price = d3.max(n_data, function (d) { return d.max_price ;}) ; for (i = 0; i < n_data.length; ++i) { for (j = 0; j < n_data[i].values.length; ++j) { var elem = n_data[i].values[j] ; elem.base = (max_max_price / 4) * (n_data.length - (i + 1)) ; var normalized_price = max_max_price * elem.price / n_data[i].max_price ; elem.price_on_base = (normalized_price / n_data.length) + elem.base ; } } console.log(n_data); /* Factorisation du code */ // Axes : function create_axis_x () { svg.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)) .transition() // <-- kinda dummy .delay(1775).remove() ; // <-- empirique, a ameliorer } function create_axis_y () { svg.append("g") .attr("class", "axis axis--y") .attr("transform", "translate(0,0)") .call(d3.axisLeft(y).ticks(20)) .transition() // <-- kinda dummy .delay(1775).remove() ; // <-- tatonnement, a revoir } function axises () { create_axis_x () ; create_axis_y () ; } // Dessiner les courbes : function area_generalizer (area_func, color_opacity) { g.selectAll(".area").data(n_data).enter().append("path") .attr("class", "area") .attr("d", function (d) { return area_func (d.values) } ) .attr("fill", function(d,i) { return color (d.key) ; }) .attr("opacity", color_opacity) g.selectAll(".area") .attr("class", "area") .transition().duration(1000) .attr("d", function (d) { return area_func (d.values) } ) .attr("fill", function(d,i) { return color (d.key) ; }) .attr("opacity", color_opacity); } // Legendes : function top_left_legend (opacity) { var legend = svg.selectAll(".legend").data(color.domain()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }) svg.selectAll(".legend") .attr ("class", "legend") .transition().duration(1000) .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }) .select("rect").attr("opacity", opacity); return legend ; } function right_legend (upper_bound, lower_bound) { var legend = svg.selectAll(".legend").data(color.domain()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { var vals = n_data[i].values ; return "translate(" + (width - 40) + "," + (y((vals[vals.length - 1][upper_bound] + vals[vals.length - 1][lower_bound]) / 2)) + ")"; }) svg.selectAll(".legend") .attr ("class", "legend") .transition().duration(1000) .attr("transform", function(d, i) { var vals = n_data[i].values ; return "translate(" + (width - 40) + "," + (y((vals[vals.length - 1][upper_bound] + vals[vals.length - 1][lower_bound]) / 2)) + ")"; }) .select("rect").attr("opacity", 0); return legend ; } // Le texte de la legende : function legend_append_text (legend) { legend.append("text") .attr("x", 50) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "start") .text(function(d) { return d; }); } // Le rectangle de la legende ; function legend_append_rect (legend, opacity) { legend.append("rect") .attr("x", 30) .attr("width", 18) .attr("height", 18) .style("fill", color) .attr("opacity", opacity); } /* Balancer les vues */ function lined () { y.domain([0, d3.max(data, function(d) { return d.price; })]); axises () ; area_generalizer (line, 1) ; var legend = top_left_legend (1); legend_append_text (legend) ; legend_append_rect (legend, 1) ; setTimeout (transparent, 2000) ; } function transparent () { y.domain([0, d3.max(data, function(d) { return d.price; })]); axises () ; area_generalizer (area, .5) ; var legend = top_left_legend (.5); legend_append_text (legend) ; legend_append_rect (legend, .5) ; setTimeout (separated, 2000) ; } function separated () { y.domain([0, d3.max(data, function(d) { return d.price; })]); create_axis_x () ; area_generalizer (separated_area, 1) ; var legend = right_legend ("price_on_base", "base") ; legend_append_text (legend) ; setTimeout (stacked, 2000) ; } function stacked () { y.domain([0, maxY]); axises () ; area_generalizer (stacked_area, 1) ; var legend = right_legend ("price_on_others", "sum_others") ; legend_append_text (legend) ; setTimeout (centered, 2000) ; } function centered () { y.domain([0, maxY]); axises () ; area_generalizer (centered_area, 1) ; var legend = right_legend ("price_on_others_centered", "sum_others_centered") ; legend_append_text (legend) ; setTimeout (lined, 2000) ; } /* start */ lined(); }); </script> </body>
https://d3js.org/d3.v4.min.js