diff -r 645786bb8587 -r 36f84e8f1ad5 cms/app-client/app/components/visu-langues.js --- a/cms/app-client/app/components/visu-langues.js Fri Jan 15 15:48:42 2016 +0100 +++ b/cms/app-client/app/components/visu-langues.js Fri Jan 15 15:49:42 2016 +0100 @@ -4,70 +4,194 @@ didInsertElement: function(){ var _this = this; - var data = google.visualization.arrayToDataTable([ - ['Location', 'Parent', 'Market trade volume (size)', 'Market increase/decrease (color)'], - ['Global', null, 0, 0], - ['Français', 'Global', 859, 859], - ['Alsacien', 'Global', 851, 851], - ['Breton', 'Global', 403, 403], - ['Occitan', 'Global', 344, 344], - ['Judéo-espagnol', 'Global', 77, 77], - ['Undetermined', 'Global', 45, 45], - ['Langues régionales', 'Global', 175, 175], - ['Langues non territoriales', 'Global', 48, 48], - ['Les Creoles', 'Global', 47, 47], - ['Guyane', 'Global', 59, 59], - ['Mayotte', 'Global', 20, 20], - ['Polynésie française', 'Global', 13, 13], - ['Wallis et Futuna', 'Global', 43, 43], - ['Nouvelle-Calédonie', 'Global', 68, 68], - ['Langues d’oïl', 'Langues régionales', 75, 75], - ['Francoprovençal', 'Langues régionales', 60, 60], - ['Corse', 'Langues régionales', 40, 40], - ['Langue des signes française (LSF)', 'Langues non territoriales', 40, 40], - ['Berbère', 'Langues non territoriales', 8, 8], - ['Creole de la Réunion', 'Les Creoles', 32, 32], - ['Creole de la Guadeloupe', 'Les Creoles', 15, 15], - ['Ndyuka-Trio Pidgin (njt)', 'Guyane', 31, 31], - ['Palikúr (plu)', 'Guyane', 6, 6], - ['Guianese Creole French (gcr)', 'Guyane', 4, 4], - ['Eastern Maroon Creole (djk)', 'Guyane', 16, 16], - ['Sranan Tongo (srn)', 'Guyane', 2, 2], - ['Maore Comorian (swb)', 'Mayotte', 2, 2], - ['Mauritian Sign Language (lsy)', 'Mayotte', 18, 18], - ['West Uvean (uve)', 'Polynésie française', 13, 13], - ['East Futuna (fud)', 'Wallis et Futuna', 23, 23], - ['Wallisian (wls)', 'Wallis et Futuna', 20, 20], - ['Nemi (nem)', 'Nouvelle-Calédonie', 15, 15], - ['Xârâcùù (ane)', 'Nouvelle-Calédonie', 12, 12], - ['Cemuhî (cam)', 'Nouvelle-Calédonie', 9, 9], - ['Xaragure (axx)', 'Nouvelle-Calédonie', 9, 9], - ['Iaai (iai)', 'Nouvelle-Calédonie', 8, 8], - ['Nêlêmwa-Nixumwak (nee)', 'Nouvelle-Calédonie', 4, 4], - ['Dehu (dhv)', 'Nouvelle-Calédonie', 2, 2], - ['Nengone (nen)', 'Nouvelle-Calédonie', 2, 2], - ['Ajië (aji)', 'Nouvelle-Calédonie', 1, 1], - ['Numee (kdk)', 'Nouvelle-Calédonie', 1, 1], - ['Yuaga (nua)', 'Nouvelle-Calédonie', 1, 1], - ['Bwatoo (bwa)', 'Nouvelle-Calédonie', 4, 4] - ]); + var margin = {top: 20, right: 0, bottom: 0, left: 0}, + width = 560, + height = 600 - margin.top - margin.bottom, + formatNumber = d3.format(",d"), + transitioning; + + var x = d3.scale.linear() + .domain([0, width]) + .range([0, width]); + + var y = d3.scale.linear() + .domain([0, height]) + .range([0, height]); + + var treemap = d3.layout.treemap() + .children(function(d, depth) { return depth ? null : d._children; }) + .sort(function(a, b) { return a.value - b.value; }) + .ratio(height / width * 0.5 * (1 + Math.sqrt(5))) + .round(false); + + var svg = d3.select("#chart_div").append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.bottom + margin.top) + .style("margin-left", -margin.left + "px") + .style("margin.right", -margin.right + "px") + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + .style("shape-rendering", "crispEdges"); + + var grandparent = svg.append("g") + .attr("class", "grandparent"); + + grandparent.append("rect") + .attr("y", -margin.top) + .attr("width", width) + .attr("height", margin.top); + + grandparent.append("text") + .attr("x", 6) + .attr("y", 6 - margin.top) + .attr("dy", ".75em"); + + d3.json("langues.json", function(root) { + initialize(root); + accumulate(root); + layout(root); + display(root); + + function initialize(root) { + root.x = root.y = 0; + root.dx = width; + root.dy = height; + root.depth = 0; + } + + // Aggregate the values for internal nodes. This is normally done by the + // treemap layout, but not here because of our custom implementation. + // We also take a snapshot of the original children (_children) to avoid + // the children being overwritten when when layout is computed. + function accumulate(d) { + return (d._children = d.children) + ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0) + : d.value; + } + + // Compute the treemap layout recursively such that each group of siblings + // uses the same size (1×1) rather than the dimensions of the parent cell. + // This optimizes the layout for the current zoom state. Note that a wrapper + // object is created for the parent node for each group of siblings so that + // the parent’s dimensions are not discarded as we recurse. Since each group + // of sibling was laid out in 1×1, we must rescale to fit using absolute + // coordinates. This lets us use a viewport to zoom. + function layout(d) { + if (d._children) { + treemap.nodes({_children: d._children}); + d._children.forEach(function(c) { + c.x = d.x + c.x * d.dx; + c.y = d.y + c.y * d.dy; + c.dx *= d.dx; + c.dy *= d.dy; + c.parent = d; + layout(c); + }); + } + } + + function display(d) { + grandparent + .datum(d.parent) + .on("click", transition) + .select("text") + .text(name(d)); - var tree = new google.visualization.TreeMap(document.getElementById('chart_div')); + var g1 = svg.insert("g", ".grandparent") + .datum(d) + .attr("class", "depth"); + + var g = g1.selectAll("g") + .data(d._children) + .enter().append("g"); + + g.classed("bla", true).on("click", selectHandler) + + g.filter(function(d) { return d._children; }) + .classed("children", true) + .on("click", transition); + + // g.selectAll(".child") + // .data(function(d) { return d._children || [d]; }) + // .enter().append("rect") + // .attr("class", "child") + // .call(rect); + + g.append("rect") + .attr("class", "parent") + // .attr("fill", (d.color || "#bbb")) + .call(rect) + .append("title") + .text(function(d) { return formatNumber(d.value); }); + + g.append("text") + .attr("dy", ".75em") + .text(function(d) { return d.name; }) + .call(text); + + function transition(d) { + if (transitioning || !d) return; + selectHandler(d); + transitioning = true; + + var g2 = display(d), + t1 = g1.transition().duration(750), + t2 = g2.transition().duration(750); + + // Update the domain only after entering new elements. + x.domain([d.x, d.x + d.dx]); + y.domain([d.y, d.y + d.dy]); + + // Enable anti-aliasing during the transition. + svg.style("shape-rendering", null); - tree.draw(data, { - minColor: '#E0EEEF', - midColor: '#7CACAE', - maxColor: '#2D7073', - headerHeight: 15, - fontColor: 'black', - showScale: true + // Draw child nodes on top of parent nodes. + svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; }); + + // Fade-in entering text. + g2.selectAll("text").style("fill-opacity", 0); + + // Transition to the new view. + t1.selectAll("text").call(text).style("fill-opacity", 0); + t2.selectAll("text").call(text).style("fill-opacity", 1); + t1.selectAll("rect").call(rect); + t2.selectAll("rect").call(rect); + + // Remove the old node when the transition is finished. + t1.remove().each("end", function() { + svg.style("shape-rendering", "crispEdges"); + transitioning = false; + }); + } + + function selectHandler (d){ + if (d.name === "Global"){ + return _this.sendAction('action', null); + } + _this.sendAction('action', d.name); + } + + return g; + } + + function text(text) { + text.attr("x", function(d) { return x(d.x) + 6; }) + .attr("y", function(d) { return y(d.y) + 6; }); + } + + function rect(rect) { + rect.attr("x", function(d) { return x(d.x); }) + .attr("y", function(d) { return y(d.y); }) + .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); }) + .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); }) + .attr("fill", function(d) { return (d.color || "#bbb")}); + } + + function name(d) { + return d.parent + ? name(d.parent) + "." + d.name + : d.name; + } }); - - function selectHandler (){ - _this.sendAction('action', data.getValue(tree.getSelection()[0].row, 0)); - } - - google.visualization.events.addListener(tree, 'select', selectHandler); - } });