A version of the previous block, but improved to speed the drawing and to make fast transitions.
Based on this block by Peter Beshai
| licence: mit |
A version of the previous block, but improved to speed the drawing and to make fast transitions.
Based on this block by Peter Beshai
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| </style> | |
| <body> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script> | |
| const width = 960, | |
| height = 670; | |
| const duration = 1500; | |
| const ease = d3.easeCubic; | |
| let timer; | |
| let currLayout = 0; | |
| var canvas = d3.select("body") | |
| .append("canvas") | |
| .attr('height', height) | |
| .attr('width', width); | |
| var context = canvas.node().getContext("2d"); | |
| var points = []; | |
| var penes = [{'Nom':'Dotze anys i un dia de reclusió temporal', 'Nombre': 11348, 'Color': '#eded07'}, | |
| {'Nom':'Sobreseïment','Nombre': 10479, 'Color': '#afa'}, | |
| {'Nom':'Absolt','Nombre': 7204, 'Color': '#7f7'}, | |
| {'Nom':'Llibertat','Nombre': 6105, 'Color': '#8f8'}, | |
| {'Nom':'Sense declaració de responsabilitats','Nombre': 5469, 'Color': '#cfc'}, | |
| {'Nom':'Mort','Nombre': 4404, 'Color': '#f00'}, | |
| {'Nom':'Vint anys de reclusió temporal','Nombre': 3826, 'Color': '#d18400'}, | |
| {'Nom':'Reclusió perpètua','Nombre': 3740, 'Color': '#d15a00'}, | |
| {'Nom':'Quinze anys de reclusió temporal','Nombre': 3560, 'Color': '#d1aa00'}, | |
| {'Nom':'Arxiu','Nombre': 3360, 'Color': '#afa'}, | |
| {'Nom':'Sis anys i un dia de presó major','Nombre': 2022, 'Color': '#d1c600'}, | |
| {'Nom':'Trenta anys de reclusió major','Nombre': 665, 'Color': '#d16500'}, | |
| {'Nom':'Pena de multa','Nombre': 648, 'Color': '#b8d100'}, | |
| {'Nom':'Sis mesos i un dia de presó menor','Nombre': 548, 'Color': '#cad100'}, | |
| {'Nom':'Dotze anys i un dia de reclusió menor','Nombre': 516, 'Color': '#eded07'}, | |
| {'Nom':'Dotze anys de presó major','Nombre': 434, 'Color': '#eded07'}, | |
| {'Nom':'Destinat a Batalló de Treballadors o a','Nombre': 298, 'Color': '#156f72'}, | |
| {'Nom':'Un any de presó menor','Nombre': 298, 'Color': '#cad100'}, | |
| {'Nom':'Desglossament en un altre procediment','Nombre': 258, 'Color': '#bbb'}, | |
| {'Nom':'Absolt i un mes d\'arrest menor','Nombre': 199, 'Color': '#e5ed04'}, | |
| {'Nom':'Tres anys i un dia de presó menor','Nombre': 178, 'Color': '#d1c600'}, | |
| {'Nom':'Nou anys de presó major','Nombre': 178, 'Color': '#d1b800'}, | |
| {'Nom':'Vuit anys de presó major','Nombre': 171, 'Color': '#d1b800'}, | |
| {'Nom':'Vint anys de reclusió major','Nombre': 11, 'Color': '#d17600'}, | |
| {'Nom':'Altres','Nombre': 11, 'Color': '#aaa'}, | |
| ]; | |
| var totalVictimes = 65990; | |
| var j = 0; | |
| penes.forEach(function(pena){ | |
| for(var i = 0; i<pena['Nombre']; i++){ | |
| points.push({'color': pena['Color'], 'x': width/2, 'y': height/2, 'order': j}); | |
| j++; | |
| } | |
| }); | |
| for(var i=j; i<totalVictimes; i++){ | |
| points.push('Altres'); | |
| } | |
| function orderedLayout(points){ | |
| let stackHeight = 220; | |
| points.forEach((point) => { | |
| point.x = 3*Math.floor(point.order/stackHeight); | |
| point.y = 3*(point.order%stackHeight);; | |
| }); | |
| return points; | |
| } | |
| function randomLayout(points){ | |
| let stackHeight = 220; | |
| shuffle(points) | |
| points.forEach((point, i) => { | |
| point.x = 3*Math.floor(i/stackHeight); | |
| point.y = 3*(i%stackHeight);; | |
| }); | |
| return points; | |
| } | |
| const layouts = [randomLayout, orderedLayout]; | |
| function draw() { | |
| context.clearRect(0,0,canvas.attr("width"),canvas.attr("height")); | |
| for (let i = 0; i < points.length; ++i) { | |
| const point = points[i]; | |
| context.fillStyle = point.color; | |
| context.fillRect(point.x, point.y, 2, 2); | |
| } | |
| } | |
| function animate(layout) { | |
| // store the source position | |
| points.forEach(point => { | |
| point.sx = point.x; | |
| point.sy = point.y; | |
| }); | |
| // get destination x and y position on each point | |
| layout(points); | |
| // store the destination position | |
| points.forEach(point => { | |
| point.tx = point.x; | |
| point.ty = point.y; | |
| }); | |
| timer = d3.timer((elapsed) => { | |
| // compute how far through the animation we are (0 to 1) | |
| const t = Math.min(1, ease(elapsed / duration)); | |
| // update point positions (interpolate between source and target) | |
| points.forEach(point => { | |
| point.x = point.sx * (1 - t) + point.tx * t; | |
| point.y = point.sy * (1 - t) + point.ty * t; | |
| }); | |
| // update what is drawn on screen | |
| draw(); | |
| // if this animation is over | |
| if (t === 1) { | |
| timer.stop(); | |
| currLayout = (currLayout + 1) % layouts.length; | |
| animate(layouts[currLayout]); | |
| } | |
| }); | |
| } | |
| animate(layouts[currLayout]); | |
| function shuffle(array) { | |
| //https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array | |
| var currentIndex = array.length, temporaryValue, randomIndex; | |
| // While there remain elements to shuffle... | |
| while (0 !== currentIndex) { | |
| // Pick a remaining element... | |
| randomIndex = Math.floor(Math.random() * currentIndex); | |
| currentIndex -= 1; | |
| // And swap it with the current element. | |
| temporaryValue = array[currentIndex]; | |
| array[currentIndex] = array[randomIndex]; | |
| array[randomIndex] = temporaryValue; | |
| } | |
| return array; | |
| } | |
| </script> | |
| </body> |