socialgekon.com
  • Hlavná
  • Dizajn Značky
  • Uverejnenie
  • Finančné Procesy
  • Projektový Manažment
Back-End

Smerom k aktualizovateľným grafom D3.js

Úvod

D3.js je open source knižnica pre vizualizácie údajov vyvinutá Mikeom Bostockom. D3 je skratka pre dokumenty riadené dátami a ako už naznačuje jej názov, knižnica umožňuje vývojárom ľahko generovať a manipulovať s prvkami DOM na základe dát. Aj keď to nie je obmedzené možnosťami knižnice, D3.js sa zvyčajne používa s prvkami SVG a ponúka výkonné nástroje na vývoj vizualizácií vektorových údajov od nuly.

Aktualizovateľný vzor grafu umožňuje jednoduché vytváranie grafov D3.js. Tweet

Začnime jednoduchým príkladom. Predpokladajme, že trénujete na závod 5k a chcete vytvoriť vodorovný stĺpcový graf počtu kilometrov, ktoré ste zabehli každý deň minulého týždňa:

var milesRun = [2, 5, 4, 1, 2, 6, 5]; d3.select('body').append('svg') .attr('height', 300) .attr('width', 800) .selectAll('rect') .data(milesRun) .enter() .append('rect') .attr('y', function (d, i) { return i * 40 }) .attr('height', 35) .attr('x', 0) .attr('width', function (d) { return d*100}) .style('fill', 'steelblue');

Ak ho chcete vidieť v akcii, pozrite si ho bl.ocks.org .



Ak tento kód vyzerá dobre, je to skvelé. Ak nie, našiel som Výukové programy Scotta Murraya byť vynikajúcim zdrojom pre začatie práce s D3.js.

Ako freelancer, ktorý pracoval stovky hodín na vývoji s D3.js, prešiel môj vývojový model vývojom, vždy s konečným cieľom vytvoriť čo najkomplexnejšie skúsenosti klientov a používateľov. Ako budem podrobnejšie rozoberať neskôr, Mike Bostockov vzor pre opakovane použiteľné grafy ponúkol osvedčenú metódu na implementáciu rovnakého grafu v ľubovoľnom počte výberov. Jeho obmedzenia sú však realizované po inicializácii grafu. Ak som chcel pomocou tejto metódy použiť prechody a vzory aktualizácií D3, bolo treba so zmenami údajov zaobchádzať úplne v rovnakom rozsahu, v akom bol vygenerovaný graf. V praxi to znamenalo implementovať filtre, rozbaľovacie ponuky, posúvače a možnosti zmeny veľkosti v rovnakom rozsahu funkcií.

Po opakovanom vyskúšaní týchto obmedzení na vlastnej koži som chcel vytvoriť spôsob, ako využiť plný výkon súborov D3.js. Napríklad počúvanie zmien v rozbaľovacej ponuke úplne samostatného komponentu a bezproblémové spustenie aktualizácií grafov zo starých údajov na nové. Chcel som mať možnosť odovzdať ovládacie prvky grafu s plnou funkčnosťou, a to spôsobom, ktorý bol logický a modulárny. Výsledkom je aktualizovateľný vzor grafu a ja prejdem svojím úplným postupom k vytvoreniu tohto vzoru.

Priebeh grafov D3.js

Krok 1: Konfiguračné premenné

Keď som začal používať D3.js na vývoj vizualizácií, stalo sa veľmi pohodlným používať konfiguračné premenné na rýchle definovanie a zmenu špecifikácií grafu. Toto umožnilo mojim mapám spracovávať všetky rôzne dĺžky a hodnoty údajov. Rovnaký kúsok kódu, ktorý zobrazoval počet kilometrov, by teraz mohol zobraziť dlhší zoznam teplôt bez akýchkoľvek štikútov:

var highTemperatures = [77, 71, 82, 87, 84, 78, 80, 84, 86, 72, 71, 68]; var height = 300; var width = 800; var barPadding = 1; var barSpacing = height / highTemperatures.length; var barHeight = barSpacing - barPadding; var maxValue = d3.max(highTemperatures); var widthScale = width / maxValue; d3.select('body').append('svg') .attr('height', height) .attr('width', width) .selectAll('rect') .data(highTemperatures) .enter() .append('rect') .attr('y', function (d, i) { return i * barSpacing }) .attr('height', barHeight) .attr('x', 0) .attr('width', function (d) { return d*widthScale}) .style('fill', 'steelblue');

Ak ho chcete vidieť v akcii, pozrite si ho bl.ocks.org .

Všimnite si, ako sú výšky a šírky pruhov zmenšené na základe veľkosti a hodnôt údajov. Jedna premenná sa zmení a o zvyšok sa postará.

Krok 2: Jednoduché opakovanie pomocou funkcií

Kódovanie by nikdy nemalo byť cvičením kopírovania a vkladania

Kódovanie by nikdy nemalo byť cvičením kopírovania a vkladania Tweet

Abstrakciou časti obchodnej logiky dokážeme vytvoriť univerzálnejší kód, ktorý je pripravený na spracovanie zovšeobecnenej šablóny údajov. Ďalším krokom je zabalenie tohto kódu do funkcie generovania, ktorá redukuje inicializáciu iba na jeden riadok. Táto funkcia obsahuje tri argumenty: údaje, cieľ DOM a objekt volieb, ktorým je možné prepísať predvolené konfiguračné premenné. Zistite, ako je to možné:

var milesRun = [2, 5, 4, 1, 2, 6, 5]; var highTemperatures = [77, 71, 82, 87, 84, 78, 80, 84, 86, 72, 71, 68, 75, 73, 80, 85, 86, 80]; function drawChart(dom, data, options) { var width = options.width || 800; var height = options.height || 200; var barPadding = options.barPadding || 1; var fillColor = options.fillColor || 'steelblue'; var barSpacing = height / data.length; var barHeight = barSpacing - barPadding; var maxValue = d3.max(data); var widthScale = width / maxValue; d3.select(dom).append('svg') .attr('height', height) .attr('width', width) .selectAll('rect') .data(data) .enter() .append('rect') .attr('y', function (d, i) { return i * barSpacing }) .attr('height', barHeight) .attr('x', 0) .attr('width', function (d) { return d*widthScale}) .style('fill', fillColor); } var weatherOptions = {fillColor: 'coral'}; drawChart('#weatherHistory', highTemperatures, weatherOptions); var runningOptions = {barPadding: 2}; drawChart('#runningHistory', milesRun, runningOptions);

Ak ho chcete vidieť v akcii, pozrite si ho bl.ocks.org .

V tejto súvislosti je tiež dôležité poznamenať si výbery súborov D3.js. Všeobecné výbery ako d3.selectAll(‘rect’) treba sa vždy vyvarovať. Ak sú súbory SVG prítomné niekde inde na stránke, všetky rect na stránke sa stanú súčasťou výberu. Namiesto toho pomocou odovzdaného odkazu DOM vytvorte jeden svg objekt, na ktorý môžete odkazovať pri pripájaní a aktualizácii prvkov. Táto technika môže tiež vylepšiť dobu chodu generovania grafov, pretože použitie pruhov podobných ako referencia tiež zabráni nutnosti opätovného výberu súboru D3.js.

Krok 3: Metóda reťazenia a výbery

Zatiaľ čo predchádzajúca kostra využívajúca konfiguračné objekty je v knižniciach JavaScript veľmi bežná, Mike Bostock, tvorca súboru D3.js, odporúča iný vzor na vytváranie opakovane použiteľných grafov. Stručne povedané, Mike Bostock odporúča implementácia grafov ako uzáverov metódami getra a setra . Aj keď implementácii grafu pridávate zložitosť, nastavenie možností konfigurácie sa pre volajúceho stáva veľmi jednoduchým jednoduchým použitím reťazenia metód:

// Using Mike Bostock's Towards Reusable Charts Pattern function barChart() { // All options that should be accessible to caller var width = 900; var height = 200; var barPadding = 1; var fillColor = 'steelblue'; function chart(selection){ selection.each(function (data) { var barSpacing = height / data.length; var barHeight = barSpacing - barPadding; var maxValue = d3.max(data); var widthScale = width / maxValue; d3.select(this).append('svg') .attr('height', height) .attr('width', width) .selectAll('rect') .data(data) .enter() .append('rect') .attr('y', function (d, i) { return i * barSpacing }) .attr('height', barHeight) .attr('x', 0) .attr('width', function (d) { return d*widthScale}) .style('fill', fillColor); }); } chart.width = function(value) { if (!arguments.length) return margin; width = value; return chart; }; chart.height = function(value) { if (!arguments.length) return height; height = value; return chart; }; chart.barPadding = function(value) { if (!arguments.length) return barPadding; barPadding = value; return chart; }; chart.fillColor = function(value) { if (!arguments.length) return fillColor; fillColor = value; return chart; }; return chart; } var milesRun = [2, 5, 4, 1, 2, 6, 5]; var highTemperatures = [77, 71, 82, 87, 84, 78, 80, 84, 86, 72, 71, 68, 75, 73, 80, 85, 86, 80]; var runningChart = barChart().barPadding(2); d3.select('#runningHistory') .datum(milesRun) .call(runningChart); var weatherChart = barChart().fillColor('coral'); d3.select('#weatherHistory') .datum(highTemperatures) .call(weatherChart);

Ak ho chcete vidieť v akcii, pozrite si ho bl.ocks.org .

Inicializácia grafu používa výber D3.js, väzbu relevantných údajov a výber DOM predáva ako this súvislosti s funkciou generátora. Funkcia generátora zalomí predvolené premenné do uzávierky a umožňuje volajúcemu ich meniť pomocou reťazenia metód s konfiguračnými funkciami, ktoré vracajú objekt grafu. Týmto spôsobom môže volajúci vykresliť ten istý graf na viac výberov súčasne alebo pomocou jedného grafu na vykreslenie toho istého grafu na rôzne výbery s rôznymi údajmi, a to všetko bez toho, aby obišiel objemný objekt možností.

Krok 4: Nový vzor pre aktualizovateľné grafy

Predchádzajúci vzorec navrhnutý Mikeom Bostockom nám dáva, ako vývojári grafov , veľa energie v rámci funkcie generátora. Vzhľadom na jednu sadu údajov a všetky odovzdané zreťazené konfigurácie kontrolujeme odtiaľ všetko. Ak je potrebné údaje zmeniť zvnútra, môžeme namiesto prečerpania od začiatku použiť vhodné prechody. Aj s vecami, ako sú zmeny veľkosti okna, sa dá manipulovať elegantne, vytvárať responzívne funkcie, ako je použitie skráteného textu alebo zmena štítkov osí.

Čo však v prípade, ak sú údaje upravené mimo rámca funkcie generátora? Alebo čo ak je potrebné zmeniť veľkosť grafu programovo? Mohli by sme znova zavolať funkciu grafu s novými údajmi a konfiguráciou novej veľkosti. Všetko by bolo prekreslené a voilà. Problém je vyriešený.

Toto riešenie bohužiaľ má množstvo problémov.

Po prvé, takmer nevyhnutne vykonávame nepotrebný výpočet inicializácie. Prečo zložitá manipulácia s údajmi, keď všetko, čo musíme urobiť, je zväčšiť šírku? Tieto výpočty môžu byť potrebné pri prvej inicializácii grafu, ale určite nie pri každej aktualizácii, ktorú musíme vykonať. Každá programová požiadavka vyžaduje určité úpravy a ako vývojári presne vieme, o aké zmeny ide. Nie viac nie menej. Navyše v rámci rozsahu grafu už máme prístup k mnohým veciam, ktoré potrebujeme (objekty SVG, aktuálne dátové stavy a ďalšie), ktoré priamo implementujú zmeny.

Vezmime si napríklad príklad stĺpcového grafu vyššie. Ak by sme chceli aktualizovať šírku a urobili by sme to prekreslením celého grafu, spustili by sme množstvo zbytočných výpočtov: nájdenie maximálnej hodnoty údajov, výpočet výšky pruhu a vykreslenie všetkých týchto prvkov SVG. Naozaj, raz width je priradená k svojej novej hodnote, jediné zmeny, ktoré musíme urobiť, sú:

width = newWidth; widthScale = width / maxValue; bars.attr('width', function(d) { return d*widthScale}); svg.attr('width', width);

Ale je to ešte lepšie. Pretože teraz máme históriu grafu, môžeme na aktualizáciu grafov používať integrované prechody D3 animovaný ľahko. Pokračovaním vyššie uvedeného príkladu pridaním prechodu na width je rovnako jednoduché ako zmena

bars.attr('width', function(d) { return d*widthScale});

do

bars.transition().duration(1000).attr('width', function(d) { return d*widthScale});

Ešte lepšie je, že ak umožníme používateľovi odovzdať nový súbor údajov, môžeme pomocou prechodov na nové údaje použiť aj výber aktualizácií D3 (vstup, aktualizácia a ukončenie). Ako však umožniť nové údaje? Ak si spomínate, naša predchádzajúca implementácia vytvorila nový nasledujúci graf:

d3.select('#weatherHistory') .datum(highTemperatures) .call(weatherChart);

Viazali sme údaje na výber D3.js a zavolali náš opakovane použiteľný graf. Akékoľvek zmeny údajov by sa museli vykonať spojením nových údajov s rovnakým výberom. Teoreticky by sme mohli použiť starý vzor a preskúmať výber pre existujúce údaje a potom aktualizovať naše zistenia o nové údaje. Nielen, že je to chaotické a komplikované pri implementácii, ale vyžadovalo by to predpoklad, že existujúci graf bol rovnakého typu a formy.

Namiesto toho s určitými zmenami v štruktúre funkcie generátora JavaScriptu môžeme vytvoriť graf, ktorý volajúcemu umožní ľahko vyvolať zmeny externe prostredníctvom reťazenia metód. Zatiaľ čo predtým, ako bola konfigurácia a údaje nastavené a potom zostali nedotknuté, môže volajúci teraz urobiť niečo také, a to aj po inicializácii grafu:

weatherChart.width(420);

Výsledkom je plynulý prechod na novú šírku z existujúceho grafu. Bez zbytočných výpočtov a s elegantnými prechodmi je výsledkom šťastný klient.

Žiadne zbytočné výpočty + elegantné prechody = šťastný klient

Žiadne zbytočné výpočty + elegantné prechody = šťastný klient Tweet

Táto funkcia navyše prichádza s miernym zvýšením úsilia vývojárov. Snahu, ktorú som však historicky považoval za hodnú času. Tu je kostra aktualizovateľného grafu:

function barChart() { // All options that should be accessible to caller var data = []; var width = 800; //... the rest var updateData; var updateWidth; //... the rest function chart(selection){ selection.each(function () { // //draw the chart here using data, width // updateWidth = function() { // use width to make any changes }; updateData = function() { // use D3 update pattern with data } }); } chart.data = function(value) { if (!arguments.length) return data; data = value; if (typeof updateData === 'function') updateData(); return chart; }; chart.width = function(value) { if (!arguments.length) return width; width = value; if (typeof updateWidth === 'function') updateWidth(); return chart; }; //... the rest return chart; }

Ak chcete vidieť úplnú implementáciu, pozrite si ju na bl.ocks.org .

Pozrime sa na novú štruktúru. Najväčšou zmenou oproti predchádzajúcej implementácii uzávierky je pridanie aktualizačných funkcií. Ako už bolo diskutované, tieto funkcie využívajú prechody a vzory aktualizácií D3.js na plynulé vykonávanie potrebných zmien na základe nových údajov alebo konfigurácií grafov. Aby boli tieto volajúcemu prístupné, do grafu sa pridávajú funkcie ako vlastnosti. A aby to bolo ešte jednoduchšie, počiatočná konfigurácia aj aktualizácie sú spracovávané rovnakou funkciou:

chart.width = function(value) { if (!arguments.length) return width; width = value; if (typeof updateWidth === 'function') updateWidth(); return chart; };

Upozorňujeme, že updateWidth budú definované až po inicializácii grafu. Ak je undefined, potom bude konfiguračná premenná globálne nastavená a použitá v závere grafu. Ak bola vyvolaná funkcia grafu, potom sú všetky prechody odovzdané znaku updateWidth funkcia, ktorá používa zmenené width premennej, aby ste vykonali potrebné zmeny. Niečo také:

updateWidth = function() { widthScale = width / maxValue; bars.transition().duration(1000).attr('width', function(d) { return d*widthScale}); svg.transition().duration(1000).attr('width', width); };

S touto novou štruktúrou sa údaje pre graf odovzdávajú reťazením metód rovnako ako akákoľvek iná konfiguračná premenná, namiesto toho, aby sa viazali na výber D3.js. Rozdiel:

var weatherChart = barChart(); d3.select('#weatherHistory') .datum(highTemperatures) .call(weatherChart);

ktorý sa stáva:

var weatherChart = barChart().data(highTemperatures); d3.select('#weatherHistory') .call(weatherChart);

Urobili sme teda niekoľko zmien a pridali sme trochu úsilia vývojárov, pozrime sa na výhody.

Povedzme, že máte novú požiadavku na funkciu: „Pridajte rozbaľovaciu ponuku, aby používateľ mohol prepínať medzi vysokými a nízkymi teplotami. A kým ste, tak urobte aj zmenu farby. “ Namiesto vymazania aktuálneho grafu, viazania nových údajov a opätovného čerpania môžete teraz uskutočniť jednoduchý hovor, keď je vybratá nízka teplota:

weatherChart.data(lowTemperatures).fillColor(‘blue’);

a užívajte si kúzlo. Nielenže ukladáme výpočty, ale pri aktualizácii vizualizácie pridávame novú úroveň porozumenia, čo predtým nebolo možné.

Tu je potrebné dôležité slovo ohľadne prechodov. Pri plánovaní viacerých prechodov na rovnaký prvok buďte opatrní. Spustenie nového prechodu implicitne zruší všetky predtým spustené prechody. V jednom prechode iniciovanom D3.js je samozrejme možné zmeniť viac atribútov alebo štýlov, ale narazil som na niektoré prípady, keď sa spúšťa viac prechodov súčasne. V týchto prípadoch zvážte použitie súbežných prechodov na nadradených a podradených prvkoch pri vytváraní aktualizačných funkcií.

Zmena filozofie

Mike Bostock predstavuje uzávery ako spôsob zapuzdrenia generovania grafov. Jeho vzor je optimalizovaný na vytvorenie rovnakého grafu s rôznymi údajmi na mnohých miestach. Počas rokov práce s D3.js som však našiel mierny rozdiel v prioritách. Namiesto toho, aby sa pomocou jednej inštancie grafu vytvorila rovnaká vizualizácia s rôznymi údajmi, nový vzor, ​​ktorý som zaviedol, umožňuje volajúcemu ľahko vytvoriť viac inštancií grafu, pričom každú z nich je možné úplne upraviť aj po inicializácii. Každá z týchto aktualizácií je navyše spracovaná s úplným prístupom k aktuálnemu stavu grafu, čo umožňuje vývojárovi eliminovať zbytočné výpočty a využívať silu súboru D3.js na vytváranie plynulejších používateľských a klientských zážitkov.

Ako zjednodušiť súbežnosť pomocou reaktívneho modelovania v systéme Android

Mobilné

Ako zjednodušiť súbežnosť pomocou reaktívneho modelovania v systéme Android
Umenie kradnúť: Ako sa stať majstrom dizajnéra

Umenie kradnúť: Ako sa stať majstrom dizajnéra

Dizajn Používateľského Rozhrania

Populárne Príspevky
Kód Buggy CakePHP: 6 najčastejších chýb, ktoré vývojári CakePHP robia
Kód Buggy CakePHP: 6 najčastejších chýb, ktoré vývojári CakePHP robia
Príručka produktového dizajnéra ku konkurenčnej analýze
Príručka produktového dizajnéra ku konkurenčnej analýze
Komplexný zoznam agilných konferencií
Komplexný zoznam agilných konferencií
Štýly typografie pre web a redakčný a tlačený dizajn
Štýly typografie pre web a redakčný a tlačený dizajn
Recenzie spoločnosti Microsoft HoloLens - Preklenutie priepasti medzi AR a VR
Recenzie spoločnosti Microsoft HoloLens - Preklenutie priepasti medzi AR a VR
 
Riaditeľ plateného média
Riaditeľ plateného média
Zlé postupy pri návrhu databázy: Robíte tieto chyby?
Zlé postupy pri návrhu databázy: Robíte tieto chyby?
Ako nájsť stiahnuté súbory na iPhone
Ako nájsť stiahnuté súbory na iPhone
Vytvorenie Sprievodcu štýlom používateľského rozhrania pre lepšie UX
Vytvorenie Sprievodcu štýlom používateľského rozhrania pre lepšie UX
Osvedčené postupy mobilného elektronického obchodu pre UX (s infografikou)
Osvedčené postupy mobilného elektronického obchodu pre UX (s infografikou)
Kategórie
Inžiniersky ManažmentInvestori A FinancovanieÚpravaUverejneniePlánovanie A PrognózaAgilnýNástroje A Výukové ProgramyRise Of RemoteDistribuované TímyProjektový Manažment

© 2023 | Všetky Práva Vyhradené

socialgekon.com