Antonio Lacković
Autor:
Antonio Lacković

Programer za C#.NET programski jezik

Responzivni grafovi sa D3.js

Za razliku od prije desetak godina, danas je teško zamisliti novu web aplikaciju bez responzivnog dizajna. Takva aplikacija teško bi prošla na tržištu jer ima previše različitih veličina ekrana na kojima se prikazuje sadržaj i korisnici ne bi bili zadovoljni. Česta su pojava i razne interaktivne vizualizacije podataka koje korisniku omogućuju brži i ljepši uvid u podatke čime se poboljšava user experience. Jedna od najpoznatijih biblioteka za interaktivnu vizualizaciju podataka je D3.js (https://d3js.org/).

 

D3

Što se tiče same izrade grafova D3 je jako fleksibilan i moguće je napraviti bilo kakve vrste grafova od kojih se najčešće koriste bar chart-ovi i scatterplot chart-ovi. To se vidi po količini primjera (https://github.com/d3/d3/wiki/Gallery) što svakako može utjecati kod odabira rješenja vizualizacije podataka. Nedavno smo imali pilot projekt u kojem je korisnikov zahtjev bio vizualizirati podatke i u kratkom periodu smo odabrali D3.js biblioteku baš zbog iznad navedenih razloga. Za prikaz grafova koristi se HTML5 svg element.

Primjer responzivnog grafa je na primjeru već gotovog scatterplot grafa (http://bl.ocks.org/d3noob/38744a17f9c0141bcd04). Primjer je malo promijenjen i prilagođen za demo. Za responzivan prikaz graf je potrebno izmijeniti tako da se inicijalno samo postave x, y osi, napune se podatcima te se dodaju linije i točke. Nakon toga je potrebno napraviti event na promjenu veličine prozora. Kod promjena dimenzija prozora potrebno je svaki put ponovno izračunavati dužinu i širinu prema kojima se podatci skaliraju. Podatke nije potrebno rekreirati, potrebno ih je samo ponovno iscrtati. Svaki demo je embed-ani primjer jsfiddle web aplikacije (https://jsfiddle.net/) i moguće je odmah pogledati izvorni kod.

 

Primjer responzivnog grafa

/* Dohvat nove veličine prozora */

var widther = window.innerWidth - 10;

var width = widther - margin.left - margin.right;

var height = window.innerHeight - margin.top - margin.bottom;

width = width - (margin.left + margin.top) / 2;

height = height - (margin.top + margin.bottom) / 2;

 

/* Postavljanje podataka prema novoj veličini */

x.range([0, width]);

y.range([height, 0]);

 

/* Postavljanje osi prema novoj veličini */

xAxis.scale(x);

yAxis.scale(y);

 

/* Postavljanje veličine svg elementa prema veličini prozora */

svg

.attr("width", width + margin.left + margin.right)

.attr("height", height + margin.top + margin.bottom);

 

/* Iscrtavanje osi prema skalianoj veličini */

svg.select(".x.axis").call(xAxis);

svg.select(".y.axis").call(yAxis);

 

/* Dodavanje novih točki */

svg.selectAll('circle')

.data(data)

.enter()

.append("circle")

.attr("transform", "translate(" + margin.left + "," + margin.top + ")")

.attr("r", 3.5);

 

/* Iscrtavanje točki prema skaliranoj veličini */

svg.selectAll('circle')

.attr("cx", function(d) { return x(d.date); })

.attr("cy", function(d) { return y(d.close); });

 

/* Iscrtavanje linije prema skaliranoj veličini */

svg.selectAll('.line').attr("d", line(data));

 

Demo

 

Prvo se izvuče nova veličina elementa u kojem se graf nalazi, u ovom slučaju je to prozor. Pomoću range() metode postavljaju se podatci, a scale() metode osi prema veličini. Nakon toga se postavi svg element na novu veličinu i iscrtaju se osi i podatci. Za liniju je potrebno proslijediti podatke prema kojima se ista iscrta. Točkama je potrebno postaviti podatke s metodom data(). Metoda enter() vraća podatke iz kolekcije koji će se prikazivati. Prvi puta će metoda enter() vraćati sve rezultate iz data kolekcije. Nakon toga je potrebno iscrtati podatke prema novoj veličini.

Taj graf je sada responzivan, skalira se promjenom veličine prozora, ali postoji problem ako se prikazuje na ekranu veličine mobilnih uređaja. Dolazi do preklapanja podataka na osima. To se isto može na jednostavan način riješiti. Potrebno je regulirati broj tick labela koje se pojavljuju na osima.

 

Primjer responzivnih osi:

/* Postavljanje tickova labela na osima*/

xAxis.ticks(Math.max(width/120, 2));

yAxis.ticks(Math.max(height/25, 3));

 

Demo

 

Metodi tick() je potrebno proslijediti broj koliko labela je potrebno prikazati na osi nad kojom se izvršava metoda. Jednostavnom matematičkom formulom se može doći do željenog rješenja.

Sada je riješen problem preklapanja na osima i jasnije se vidi prikaz. Ako je potrebna interakcija s grafom, na uređajima s malim ekranom je gotovo nemoguće pogoditi točku. Potrebno je prilagoditi broj vrhova na grafu, ali to utječe i na iscrtavanje linije pa je istu potrebno prilagoditi broju vrhova.

 

Primjer skaliranja sa rezolucijom

/* Postavljanje minimalnog broja pixela između dvije točke */

min50Pixel = data.length * 50 / width;

 

/* Filtriranje podataka prema postavljenim pixelima */

dataResampled = data.filter(function(d, i) {

return i % Math.ceil(min50Pixel) == 0;

});

 

/* Iscrtavanje linije prema skaliranoj veličini i filtriranim podatcima */

svg.selectAll('.line')

.datum(dataResampled)

.attr("d", line(dataResampled));

 

/* Dodavanje novih točki prema filtriranim podatcima */

svg.selectAll('circle')

.data(dataResampled)

.enter()

.append("circle")

.attr("r", 3.5)

.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

 

/* Iscrtavanje točki prema skaliranoj veličini */

svg.selectAll('circle').data(dataResampled)

.attr("cx", function(d) { return x(d.date); })

.attr("cy", function(d) { return y(d.close); });

 

/* Brisanje točki prema filtriranim podatcima */

svg.selectAll('circle').data(dataResampled).exit().remove();

 

Demo

 

Najprije je potrebno izvući minimalni broj pixel-a između dva elementa (točke) i koristeći filter() metodu proslijediti funkciju koja će filtrirati podatke. Drugi dio je isti kao i kod prvog primjera, ali s filtriranim podatcima, dakle potrebno je dodati nove točke. Taj dio se odvija samo kod povećavanja prozora, jer smanjivanjem prozora broj točki se može samo smanjiti. Nakon što su dodani svi filtrirani podatci potrebno ih je iscrtati prema novoj veličini prozora. Kao što se metodom enter() dobiju samo novi podatci za prikaz tako se i metodom exit() dobiju podatci koji više nisu u kolekciji za prikaz, pa ih je potrebno obrisati metodom remove().

Graf iz primjera je sada responzivan i bez ikakvih preklapanja osi i vrhova linije, te je poboljšana interakcija s grafom na uređajima s bilo kakvom veličinom ekrana.

 

ZAKLJUČAK

D3.js je jako moćna i fleksibilna open source biblioteka, ima opisnu dokumentaciju, te su moguće izrade bilo kakvih grafova. Na webu postoji puno primjera i StackOverflow pitanja i odgovora (https://stackoverflow.com/search?q=d3js) što je veliki bonus kod odabira rješenja za vizualizaciju podataka jer je lakše nešto napraviti uz veću količinu primjera. D3 je svakako jedno od vodećih rješenja vizualizacije podataka.

Popularne teme
.NET ABAP ADFS Agile Always On Anemic Model Angular Azure Backbone benchmark BI BI projekti Bootstrap building people business inteligence Business Intelligence Change Chrome CI CITCON Claims compile Continuous Delivery continuous deployment Continuous Integration CSR d3js data data visualization Data visualization alati DDD dekompozicija dependency injection dinamička forma dinamički parametri dinamički query distribuirani razvoj Domain-Driven design DOP društvena odgovornost edge-based video analytics Eliminating waste enkapsulacija enterprise razvoj softvera ERP ETL Excel FIORI Frontend game Geopackage GPKG GIS Git Groovy heat map HICCUPS Hichert HTML IBCS interoperability invision IoT IPSO izvještavanje java JavaFX Javascript Jazz Build Engine JBE Jenkins jquery jqueryui jsfiddle JVM Kaizen Kanban king KING ICT Kingovci Knockout kvaliteta lambde leadership Lean legacy code M language Management Maven Metodologija microservices Microsoft mobile Mobility mockups moć monday game NetWeaver network nodejs oblikovni obrasci OGC OKR open source optimizacija organizacija organizacijska struktura OutOfMemoryError outsourcing overengineering paginacija Performance performanse PERT PMI PMP; Agile; Project management; Scrum; KING ICT; razvoj; metodologija podatkovni skup pouzdanost Power BI Power Map Power Pivot Power Query Power View pretraga proces procjena Product Owner programming proizvod Project manager projektni plan radar Rational Team Concert razvoj tima refaktoriranje Release resize responsive charts REST retrospektiva Rich-Domain model Roko Roić rolling wave planning RTC SAP scale scatterplot chart Scrum scrum team scrum tim service boundaries single responsibility principle Single Sign-On smart metering SoapUI social responsibility softver Software software prototyping Software Testing Club Spring Boot SQL standard sustav videonadzora svg tdd Team team building team development Team Foundation Server tech tehnologije terminski plan Testing tim timesheet timovi Toggl.com touch transakcijski nadzor tražilica underengineering unit testing Uspjeh Visual Studio vodstvo vodstvo leadership moć društvena odgovornost DOP social responsibility CSR vođenje projekata WBS Web Zagreb STC

PRIJAVA NA NEWSLETTER

Najnovije novosti iz ICT svijeta