În această serie din două părți, vom combina elementul versatil de canvas cu biblioteca robustă jQuery pentru a crea un plugin pentru graficele de bare. În această primă parte, vom codifica logica de bază a plugin-ului ca versiune independentă.
Astăzi, vom crea un plugin pentru bare grafice. Nu este un plugin obișnuit. Vom arăta o dragoste jQuery cu elementul de panza pentru a crea un plugin foarte robust.
În acest articol din două părți, vom începe de la început prin implementarea logicii plugin-ului ca script independent, refăcând-o într-un plugin și adăugând în final toate bomboanele suplimentare de pe partea de sus a codului plugin-ului. În această primă parte, vom aborda numai implementarea logicii centrale.
Aveți nevoie de un exemplu înainte de a începe? Poftim!
Mulțumit? Interesat încă? Să începem.
Pluginul nostru trebuie să realizeze câteva lucruri de bază în timp ce nu face alte lucruri. Permiteți-mi să clarific:
Pe măsură ce suntem înflăcărători în lumea tehnologiei de ultimă oră, care nu este pe deplin specificată, avem unele dependențe. Pentru ca elementul canvas să funcționeze, cele mai moderne browsere sunt suficiente. Dar, din moment ce facem uz de noul API de redare a textului, avem nevoie de construiri noi. Navigatorii care utilizează motorul Webkit r433xx și de mai sus sau motorul Gecko 1.9.1 și de mai sus ar trebui să fie platforme excelente pentru plugin. Vă recomandăm să luați o construcție de noapte Chromium sau Firefox.
Aș dori să menționez că plugin-ul nostru este exclusiv în scopuri de învățare. Acest plugin nu este în nici un caz menit să înlocuiască alte plug-in-uri cu grafică completă precum Flot, Plotr și altele asemenea. De asemenea, codul va fi cât se poate de detaliat. Ai putea scrie departe, departe un cod mai eficient, dar de dragul învățării, totul va fi la fel de necomplicat. Simțiți-vă liber să o refacționați în favoarea eficienței codului dvs. de producție.
OMG WTF HAX
An | Vânzări |
---|---|
2009 | 130 |
2008 | 200 |
2007 | 145 |
2006 | 140 |
2005 | 210 |
2004 | 250 |
2003 | 170 |
2002 | 215 |
2001 | 115 |
2000 | 135 |
1999 | 110 |
1998 | 180 |
1997 | 105 |
Nimic special despre marcaj. Voi face oricum o scurtă trecere în revistă.
Înainte de a începe Javascript, permiteți-mi să explic sistemul de coordonate de pânză. Colțul din stânga sus acționează ca originea, adică (0, 0). Punctele sunt apoi măsurate cu privire la origine, cu x în creștere de-a lungul dreptului și y crescând de-a lungul stângii. Pentru înclinația matematică, lucrăm în mod efectiv în cadranul 4, cu excepția faptului că luăm valoarea absolută a y în loc de valoarea ei negativă. Dacă ați lucrat cu grafică în alte limbi, ar trebui să fiți acasă aici.
Rutina de randare a dreptunghiului canvasului va fi utilizată extensiv prin intermediul articolului pentru a reda barele, grila și alte elemente. Având în vedere acest lucru, să examinăm puțin aceste rutine.
Dintre cele trei rutine disponibile, vom folosi fillRect și strokeRect metode. fillRect metoda de fapt umple dreptunghiul rendered în timp ce strokeRect metoda numai loveste dreptunghiurile. În afară de aceasta, ambele metode iau aceiași parametri.
Ca întotdeauna, vă recomandăm să descărcați codul sursă și să îl aveți pe o parte pentru referință. Este mai ușor să te uiți la imaginea de ansamblu și să analizezi fiecare funcție una câte una decât să privești fiecare funcție în parte și apoi să creezi imaginea de ansamblu în mintea ta.
Var barSpacing = 20, barWidth = 20, cvHeight = 220, numYlabels = 8, xOffset = 20, gWidth = 550, gHeight = 200; var maxVal, gValues = [], xLabels = [], yLabels = []; var cv, ctx;
Aceste variabile mențin valori codate greu pentru a ne ajuta în poziționarea și aspectul graficului și barelor individuale.
Cu motorul selector al lui jQuery devine foarte ușor pentru noi să obținem datele de care avem nevoie. Aici avem o serie de modalități de accesare a elementelor necesare. Permiteți-mi să explic câteva dintre ele:
$ ("tr") copii ("td: impar") fiecare (functie () // cod aici);
Cea mai simplă modalitate de a accesa rândurile necesare. Se caută a tr element și apoi accesează toate celelalte td element. Ea nu reușește atunci când aveți mai mult de un tabel pe pagină.
$ ("# data") găsiți ("td: odd") fiecare (funcția () // code here);
O cale mult mai dreaptă. Trecem în ID-ul tabelului și apoi accesăm fiecare rând.
$ ("# data tr td: impar") fiecare (functie () // cod aici);
La fel ca mai sus, cu excepția faptului că folosim doar sintaxa selectorului de stil CSS.
$ ("# data tr td: nth-child (2)") fiecare (funcția () // cod aici);
Versiunea pe care o vom folosi astăzi. Acest mod este mult mai bine dacă trebuie să luăm datele dintr-un rând diferit sau, dacă este necesar, mai multe rânduri.
Versiunea finală arată astfel:
funcția grabValues () // Accesați celula de tabelă cerută, extrageți și adăugați valoarea acesteia la matricea valorilor. $ ("# data tr td: nth-child (2)") fiecare (functie () gValues.push ($ (this) .text ()); // Accesați celula de tabelă cerută, extrageți și adăugați valoarea acesteia la matricea xLabels. $ ("# date tr td: nth-child (1)") fiecare (functie () xLabels.push ($ (this) .text ());
Nimic nu este complicat aici. Utilizăm fragmentul de cod menționat mai sus pentru a adăuga valoarea celulei de tabelă la gValues matrice. Apoi, facem același lucru, cu excepția faptului că accesăm prima celulă de tabel pentru a extrage eticheta necesară pentru axa x. Am încapsulat logica extragerii de date la funcția proprie pentru reutilizarea și lizibilitatea codului.
function initCanvas () // Incearca sa accesezi elementul canvas si sa arunci o eroare daca nu este disponibila cv = $ ("# graph"). get (0); dacă (! cv) retur; // Încercați să obțineți un context 2D pentru panza și aruncați o eroare dacă nu puteți să ctx = cv.getContext ('2d'); dacă (! ctx) retur;
Rutină initializare canvas. În primul rând încercăm să accesăm elementul de pânză în sine. Noi aruncăm o eroare dacă nu putem. În continuare, încercăm să obținem o referință la contextul de redare 2d prin getContext și aruncă o eroare dacă nu putem face acest lucru.
Înainte de a intra în redarea reală a graficului în sine, trebuie să ne uităm la o serie de funcții de utilitate care ne ajută foarte mult în acest proces. Fiecare dintre ele este mică de la sine, dar va fi utilizată extensiv în codul nostru.
funcția maxValues (arr) maxVal = 0; pentru (i = 0; iO funcție mică care iterează prin matricea trecută și actualizează maxval variabil. Rețineți că umidem valoarea maximă cu 10% pentru scopuri speciale. Dacă valoarea maximă este lăsată ca atare, atunci bara reprezentând valoarea cea mai de sus va atinge marginea elementului de pânză pe care nu o dorim. În acest sens, se emite un increment de 10%.
Normalizarea valorii
scară funcțională (param) retur Math.round ((param / maxVal) * gHeight);O funcție mică pentru a normaliza valoarea extrasă în raport cu înălțimea elementului de panza. Această funcție este utilizată extensiv în alte funcții și direct în codul nostru pentru a exprima valoarea în funcție de înălțimea pânzei. Are un singur parametru.
Întoarcerea Coordonatorului X
funcția x (param) retur (param * barWidth) + (param + 1) * barSpacing) + xOffset;Returnează ordonata x la fillRect pentru a ne ajuta în poziționarea fiecărui bare individual. O să explic acest lucru mai detaliat când este folosit.
Returnează Coordonatul Y
funcția y (param) întoarcere gHigh - scale (param);Returnează ordinul y la fillRect metodă pentru a ne ajuta în poziționarea fiecărei bare individuale. Mai multe explicații mai târziu.
Returnați lățimea
lățimea funcției () return barWidth;Returnează lățimea fiecărei bare individuale.
Revenind la înălțime
înălțimea funcției (param) scară înapoi (param);Returnează înălțimea barei de trasat. Utilizează scară funcția de a normaliza valoarea și apoi o returnează apelantului.
Desenarea etichetelor axei X
funcția drawXlabels () ctx.save (); ctx.font = "10px" arial ""; ctx.fillStyle = "# 000"; pentru (indice = 0; indexO funcție simplă pentru a face etichetele axei x. Salvăm mai întâi starea actuală a pânzei, inclusiv toate setările de randare, astfel încât tot ce facem în interiorul funcțiilor să nu scurgă niciodată. Apoi am setat dimensiunea și fontul etichetelor. Apoi, vom itera prin xLabels și apelați fillText de fiecare dată pentru a face eticheta. Noi folosim X pentru a ne ajuta în poziționarea etichetelor.
Desenarea etichetelor axei Y
funcția drawYlabels () ctx.save (); pentru (indice = 0; indexO funcție mai puțin verbală. Salvăm mai întâi starea actuală a pânzei și apoi continuăm. Apoi împărțim lui maxval valoare în n elemente în cazul în care variabila numYlabels dictează n. Aceste valori sunt apoi adăugate la yLabels matrice. Acum, așa cum am arătat mai sus, fillText se cere să se deseneze etichetele individuale cu y care ne ajută în poziționarea fiecărei etichete individuale.
Facem un zero în partea de jos a pânzei pentru a termina desenarea etichetelor Y..
Desenarea graficului
funcția drawGraph () pentru (index = 0; indexFuncția care atrage barele efective în graficul de bare. Iterate prin gValues și face fiecare bară individuală. Noi folosim fillRect pentru a desena barele. După cum sa explicat mai sus, metoda are patru parametri, fiecare dintre care este îngrijit de funcțiile noastre de utilitate. Indicele curent al buclă este trecut la funcțiile noastre ca parametri împreună cu valoarea reală deținută în matrice, după cum este necesar.
X funcția returnează coordonatul x al barei. De fiecare dată, este incrementat de valoarea sumei barWidth și barSpacing variabile.
y funcția calculează diferența dintre înălțimea elementului de panza și datele normalizate și o returnează. Știu că sună un pic turbionar, dar acest lucru se datorează faptului că valorile y pe grila de canvas cresc pe parcursul deplasării, în timp ce în graficul nostru valorile y cresc pe treaptă în sus. Astfel, trebuie să facem o mică lucrare pentru ao face să funcționeze așa cum dorim.
lăţime funcția returnează lățimea barelor individuale.
înălţime funcția returnează valoarea normalizată care urmează să fie folosită ca înălțimea barei care urmează să fie desenată.
rezumat
În această primă parte, am implementat logica de bază a plug-in-ului nostru ca versiune independentă cu aspectul și caracteristicile oaselor goale. Am analizat sistemul de coordonate de canvas, metodele de randare a dreptunghiului, unele extragere de date minuțioase folosind jQuery's awesomeness, am privit cum etichetele sunt desenate și, în cele din urmă, sa uitat la logica din spatele redării graficul în sine.
La sfârșitul acestui articol, rezultatul ar trebui să arate așa.
Urmatorul!
Actuala noastră punere în aplicare este destul de lipsită într-adevăr. Pare a fi neclintit, nu poate crea mai multe grafice pe aceeași pagină, și să o facem față, este mai degrabă spartan pe frontul caracteristicilor. Vom aborda toată săptămâna viitoare. În următorul articol vom:
- Refactor codul nostru spre a face un plugin complet jQuery.
- Adăugați niște bomboane ochi.
- Includeți câteva caracteristici minunate.
Întrebări? Critici? Laudele? Simțiți-vă libertatea de a lovi comentariile. Vă mulțumim că ați citit și, când sunteți gata, treceți la partea a doua!
- Urmăriți-ne pe Twitter sau abonați-vă la feed-ul RSS NETTUTS pentru mai multe tutoriale și articole zilnice de dezvoltare web.