Datavisualisering – kul med statistik och D3.js
Datavisualisering – och "infographics" – är verkligen något som jag alltid har älskat och varit fascinerad av. När jag var liten kunde jag spendera timmar på att studera grafer och diagram i olika uppslagsverk och tidningar. Idag är den stora "förebilden" Nicholas Feltron (tycka vad man vill om Facebooks "Timeline" som han var med och skapade) som minutiöst håller reda på all möjligt statistik om sitt liv, och sedan släpper dem som "årliga rapporter" som visar grafer över allt som han har varit med om och gjort under året.
Att skapa infografik själv är inget som jag varken är vidare duktig på, eller har försökt göra. Men jag håller just nu på med ett projekt där jag ska visualisera viss data för att ge en snabb överblick – och hade tänkt att testa något annat än Google Charts API, nämligen D3.js (D3 = Data Driven Documents) som är ett mycket kraftfullt JavaScript-bibliotek för att plottra ut grafer och diagram från data. Haken med D3.js är ju dock att man bör hantera sin gymnasiematte för att få ett någorlunda bra resultat...
Här nedan visar jag en mycket simpelt diagram över de fem mest förekommande internetleverantörerna (procentuellt) som besökarna av min webbplats använder (fungerar endast i "moderna webbläsare", alltså inte < IE9. Försökt att göra så att den anpassas på bredden – men kan se lite lustigt ut på t.ex. en iPhone). Och om du missade animationen, ladda om sidan:
Det var betyderligt lättare att komma igång med än vad jag hade räknat med, och tänker definitivt fortsätta att experimentera med det för att försöka göra mer avancerade saker.
Här nedan finns den fulla källkoden (kommenterad) för den som är intresserad:
1<script type="text/javascript">23 //Ange höjden och bredden på svg-elementet4 var svgHeight = 220;5 var svgWidth = '100%';6 //Skapa en skala med 10 färger som vi kan använda7 var color = d3.scale.category10();89 //Ange datan i JSON10 var data = [11 {name: 'Telia', visitors: 30},12 {name: 'ComHem', visitors: 18},13 {name: 'Tele2', visitors: 12},14 {name: 'Telenor', visitors: 10},15 {name: 'Tre', visitors: 5},16 ];1718 //Skapa svg-elementet och append:a den till div#isp19 var svg = d3.select('#isp').append('svg:svg')20 .attr("width", svgWidth)21 .attr("height", svgHeight);2223 var elementWidth = document.getElementById("isp");24 //Ett litet extra steg, då den här webbplatsen använder25 //responsiv design, så vill man ju ha bredden på #isp26 elementWidth = elementWidth.offsetWidth;27 //Avståndet mellan cirklarna28 var spacing = elementWidth / (data.length+1);2930 //Skapa cirklar31 svg.selectAll("circle")32 .data(data)33 .enter().append("svg:circle")34 .attr("class", "circle")35 //Koordinater i x och y-led, samt radien36 .attr("cx", 0)37 .attr("cy", 100)38 .attr("r", function(d) {39 // d = datum (data i singular)40 // besökarantalet i procent ggr 341 // anger cirkelns radie42 return d.visitors * 3}43 )44 .style("stroke", "#fff")45 //"Mappa" en färg till cirkeln46 .style("fill", function(d, i) {47 return color(i % 3)48 })49 //En fin liten animation.50 //Cirklarna börjar alla på koordinaterna51 // 0x 100y, men animeras till sin "riktiga"52 // x-position53 .transition()54 .delay(100)55 .duration(2000)56 .attr("x", function(d, i) {57 // Placera cirkeln i x-led:58 // avståndet mellan cirklarna + indexet för59 // datan (ex. 0 = telia, 1 = ComHem etc.)60 return spacing * (i+1);61 });6263 //Typ samma som för ovan, men append:ar text64 svg.selectAll("text")65 .data(data)66 .enter().append("svg:text")67 .attr("x", 0)68 .attr("y", 105)69 .attr("text-anchor", "middle")70 .text(function(d) { return d.name;})71 .attr("fill", "#000;")72 .transition()73 .delay(100)74 .duration(2000)75 .attr("x", function(d, i) {76 return spacing * (i+1);77 });78</script>
1<script type="text/javascript">23 //Ange höjden och bredden på svg-elementet4 var svgHeight = 220;5 var svgWidth = '100%';6 //Skapa en skala med 10 färger som vi kan använda7 var color = d3.scale.category10();89 //Ange datan i JSON10 var data = [11 {name: 'Telia', visitors: 30},12 {name: 'ComHem', visitors: 18},13 {name: 'Tele2', visitors: 12},14 {name: 'Telenor', visitors: 10},15 {name: 'Tre', visitors: 5},16 ];1718 //Skapa svg-elementet och append:a den till div#isp19 var svg = d3.select('#isp').append('svg:svg')20 .attr("width", svgWidth)21 .attr("height", svgHeight);2223 var elementWidth = document.getElementById("isp");24 //Ett litet extra steg, då den här webbplatsen använder25 //responsiv design, så vill man ju ha bredden på #isp26 elementWidth = elementWidth.offsetWidth;27 //Avståndet mellan cirklarna28 var spacing = elementWidth / (data.length+1);2930 //Skapa cirklar31 svg.selectAll("circle")32 .data(data)33 .enter().append("svg:circle")34 .attr("class", "circle")35 //Koordinater i x och y-led, samt radien36 .attr("cx", 0)37 .attr("cy", 100)38 .attr("r", function(d) {39 // d = datum (data i singular)40 // besökarantalet i procent ggr 341 // anger cirkelns radie42 return d.visitors * 3}43 )44 .style("stroke", "#fff")45 //"Mappa" en färg till cirkeln46 .style("fill", function(d, i) {47 return color(i % 3)48 })49 //En fin liten animation.50 //Cirklarna börjar alla på koordinaterna51 // 0x 100y, men animeras till sin "riktiga"52 // x-position53 .transition()54 .delay(100)55 .duration(2000)56 .attr("x", function(d, i) {57 // Placera cirkeln i x-led:58 // avståndet mellan cirklarna + indexet för59 // datan (ex. 0 = telia, 1 = ComHem etc.)60 return spacing * (i+1);61 });6263 //Typ samma som för ovan, men append:ar text64 svg.selectAll("text")65 .data(data)66 .enter().append("svg:text")67 .attr("x", 0)68 .attr("y", 105)69 .attr("text-anchor", "middle")70 .text(function(d) { return d.name;})71 .attr("fill", "#000;")72 .transition()73 .delay(100)74 .duration(2000)75 .attr("x", function(d, i) {76 return spacing * (i+1);77 });78</script>