I denne todelte serien kombinerer vi det allsidige lerretelementet med det robuste jQuery-biblioteket for å lage et bargrafikk-plugin. I denne første delen skal vi kode kjernelogikken for plugin som en frittstående versjon.
I dag skal vi lage et bardiagramplugin. Ikke en vanlig plugin, husk deg. Vi viser noen jQuery-kjærlighet til lerretelementet for å lage et meget robust plugin.
I denne todelt artikkelen vil vi starte fra begynnelsen ved å implementere logikken til pluginet som et frittstående skript, refactoring det til et plugin og så til slutt legge til alle de ekstra øyeformene på toppen av plugin-koden. I denne første delen skal vi bare avtale med å implementere kjernelogikken.
Trenger du et eksempel før vi kommer i gang? Værsågod!
Fornøyd? Interessert ennå? La oss begynne.
Vår plugin trenger å utføre noen grunnleggende ting mens du ikke gjør noen andre ting. La meg forklare:
Som vi delver i verden av banebrytende, fortsatt ikke helt spesifisert, teknologi, har vi noen avhengigheter. For lerretelementet til arbeid, er de fleste moderne nettlesere tilstrekkelig. Men siden vi bruker den nye tekstgjenopprettings-API-en, trenger vi nyere bygg. Nettlesere som bruker Webkit-motoren r433xx og over eller Gecko-motoren 1.9.1 og høyere, bør være gode plattformer for plugin. Jeg anbefaler å ta en nattlig konstruksjon av Chromium eller Firefox.
Jeg vil gjerne nevne at vår plugin er rent for læringsformål. Dette pluginet er på ingen måte ment å erstatte andre fullverdige grafikkplugger som Flot, Plotr og så videre. Også koden kommer til å være så ordentlig som mulig. Du kan skrive langt, langt Mer effektiv kode, men for lærings skyld er alt som skal være så ukomplisert som mulig. Du kan gjerne reflektere den til fordel for effektiviteten i produksjonskoden din.
OMG WTF HAX
År | salgs~~POS=TRUNC |
---|---|
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 |
Ingenting spesielt med markeringen. Jeg vil likevel gjøre en rask oversikt.
Før vi starter Javascript, la meg forklare lerretskoordinatsystemet. Det øverste venstre hjørnet virker som opprinnelsen, dvs. (0, 0). Poeng blir da målt med hensyn til opprinnelsen med x økende langs høyresiden og y øker til venstre. For den matematisk tilbøyelige, jobber vi effektivt i fjerde kvadrant bortsett fra at vi tar absolutt verdien av y i stedet for sin negative verdi. Hvis du har jobbet med grafikk på andre språk, bør du være hjemme her.
Canvas 'rektangel rendering rutine vil bli brukt omfattende gjennom ut artikkelen for å gjengi stolper, rutenettet og noen andre elementer. Med det i tankene, la oss ta en kort titt på de rutinene.
Av de tre tilgjengelige rutene vil vi bruke fillRect og strokeRect metoder. De fillRect Metoden fyller faktisk det gjengitte rektangelet mens strokeRect Metoden strekker bare rektanglene. Annet enn det, tar begge metodene de samme parameterne.
Som alltid anbefaler jeg sterkt at du laster ned kildekoden og har den på siden for referanse. Det er lettere å se på det store bildet og analysere hver funksjon en etter en, se hver enkelt funksjon individuelt og deretter lage det store bildet i tankene dine.
var barSpacing = 20, barWidth = 20, cvHeight = 220, numYlabels = 8, xOffset = 20, gWidth = 550, gHeight = 200; var maxVal, gValues = [], xLabels = [], yLabels = []; var cv, ctx;
Disse variablene har hardkodede verdier for å hjelpe oss med posisjonering og layout av grafen og de enkelte stolpene.
Med jQuery's sterke selektormotor blir det veldig enkelt for oss å få de dataene vi trenger. Her har vi en rekke måter å få tilgang til de nødvendige elementene. La meg forklare noen nedenfor:
$ ("tr"). barn ("td: oddetall"). hver (funksjon () // kode her);
Den enkleste måten å få tilgang til de nødvendige radene. Ser etter en tr element og deretter tilgang til hverandre td element. Mislykkes når du har mer enn ett bord på siden din.
$ ("# data"). finn ("td: oddetall"). hver (funksjon () // kode her);
En mye mer rett frem vei. Vi passerer inn i ID på bordet og får tilgang til hver andre rad.
$ ("# data tr td: odd"). hver (funksjon () // kode her);
Samme som ovenfor, bortsett fra at vi bare bruker CSS stilvelger-syntaks.
$ ("# data tr td: nth-child (2)"). hver (funksjon () // kode her);
Den versjonen vi skal bruke i dag. Denne måten er mye bedre hvis vi trenger å ta data fra en annen rad eller, om nødvendig, flere rader.
Den endelige versjonen ser slik ut:
funksjon grabValues () // Få tilgang til den nødvendige tabellcellen, trekk ut og legg til verdien til verdiene array. $ ("# data tr td: nth-child (2)"). hver (funksjon () gValues.push ($ (dette) .text ());); // Få tilgang til den nødvendige tabellcellen, utdrag og legg til verdien til xLabels-arrayet. $ ("# data tr td: nth-barn (1)"). hver (funksjon () xLabels.push ($ (dette) .text ()););
Ingenting komplisert her. Vi bruker kodestykket som er nevnt ovenfor for å legge til verdien av tabellcellen til gValues array. Deretter gjør vi det samme bortsett fra at vi åpner den første tabellcellen for å trekke ut den nødvendige etiketten for x-aksen. Vi har innkapslet datautvinningslogikken til sin egen funksjon for kodegenbruk og lesbarhet.
funksjon initCanvas () // Prøv å få tilgang til lerretelementet og kaste en feil hvis den ikke er tilgjengelig cv = $ ("# graph"). få (0); hvis (! cv) return; // Prøv å få en 2D-kontekst for lerretet og kaste en feil hvis det ikke er mulig å ctx = cv.getContext ('2d'); hvis (! ctx) return;
Rutinemessig lærred initialisering. Først prøver vi å få tilgang til lerretelementet selv. Vi kaster en feil hvis ikke. Deretter prøver vi å få en referanse til 2d-renderingskonteksten gjennom getContext metode og kaste en feil hvis vi ikke klarer å gjøre det.
Før vi går inn i selve gjengivelsen av grafen selv, må vi se på en rekke bruksfunksjoner som hjelper oss sterkt i prosessen. Hver av dem er liten av seg selv, men vil bli brukt mye i hele koden vår.
funksjon maxValues (arr) maxVal = 0; for (i = 0; iEn liten funksjon som iterates gjennom passordet og oppdaterer Maxval variabel. Vær oppmerksom på at vi blåser maksimumsverdien med 10% til spesielle formål. Hvis maksimumverdien er igjen som den er, vil linjen som representerer den øverste verdien, berøre kanten av lerretelementet som vi ikke vil ha. Med det i betraktning er en 10% økning utstedt.
Normalisering av verdien
funksjonsskala (param) return Math.round ((param / maxVal) * gHeight);En liten funksjon for å normalisere den ekstraherte verdien med hensyn til høyde på lerretelementet. Denne funksjonen brukes mye i andre funksjoner og direkte i vår kode for å uttrykke verdien som en funksjon av lerretets høyde. Tar en enkelt parameter.
Returnerer X-koordinaten
funksjon x (param) retur (param * barWidth) + ((param + 1) * barSpacing) + xOffset;Returnerer x ordinaten til fillRect å hjelpe oss med å plassere hver enkelt bar. Jeg vil forklare dette litt mer detaljert når det blir brukt.
Returnerer Y-koordinaten
funksjon y (param) retur gHeight - skala (param);Returnerer y ordinaten til fillRect metode for å hjelpe oss med posisjoneringen av hver enkelt bar. Flere forklaringer litt senere.
Tilbake til bredden
funksjonsbredde () return barWidth;Returnerer bredden på hver enkelt linje.
Returnerer høyden
funksjonshøyde (param) returskala (param);Returnerer høyden på linjen som skal tegnes. Bruker den skala fungere for å normalisere verdien og deretter returnere den til den som ringer.
Tegne X-akse-etikettene
funksjon drawXlabels () ctx.save (); ctx.font = "10px 'arial'"; ctx.fillStyle = "# 000"; for (indeks = 0; indeksEn enkel funksjon for å gjengi etikettene til x-aksen. Vi lagrer først den nåværende tilstanden på lerretet, inkludert alle gjengivelsesinnstillingene, slik at alt vi gjør inne i funksjonene aldri lekker ut. Deretter setter vi størrelsen og fonten på etikettene. Deretter gjenspeiler vi gjennom xLabels array og ring til fillText Metode hver gang å gjøre etiketten. Vi bruker x Fungerer for å hjelpe oss med å plassere etikettene.
Tegne Y-akse-etikettene
funksjon drawYlabels () ctx.save (); for (indeks = 0; indeksEn litt mer ordentlig funksjon. Vi lagrer først lerretets nåværende tilstand og fortsetter deretter. Neste deler vi Maxval s Verdien inn i n elementer der variabelen numYlabels dikterer n. Disse verdiene legges da til yLabels array. Nå, som vist ovenfor, fillText Metoden kalles for å tegne de enkelte etikettene med y Funksjonen hjelper oss med å plassere hver enkelt etikett.
Vi gjør en null nederst på lerretet for å fullføre tegningen av Y-etikettene.
Tegning av grafen
funksjon drawGraph () for (index = 0; indexFunksjonen som trekker de faktiske stolpene i strekediagrammet. Iterates gjennom gValues array og gjør hver enkelt bar. Vi bruker fillRect metode for å tegne stolpene. Som forklart ovenfor, tar metoden fire parametre, som hver er tatt vare på av våre bruksfunksjoner. Den nåværende indeksen av sløyfen overføres til våre funksjoner som parametere sammen med den faktiske verdien som holdes i matrisen, etter behov.
De x funksjonen returnerer x-koordinaten til linjen. Hver gang økes den med verdien av summen av barWidth og barSpacing variabler.
De y funksjonen beregner forskjellen mellom lerretelementets høyde og de normaliserte dataene og returnerer den. Jeg vet at dette høres litt opp, men dette skyldes det faktum at y-verdiene på lerretgitteret øker ved å flytte ned mens i grafen øker y-verdiene ved å flytte opp. Dermed må vi gjøre litt arbeid for å få det til å fungere som vi ønsker.
De bredde funksjonen returnerer bredden på de enkelte stolpene selv.
De høyde funksjon returnerer bare den normaliserte verdien som skal brukes som høyden på linjen som skal tegnes.
Sammendrag
I denne første delen har vi implementert basalogikken til plugin-modulen vår som en frittstående versjon med utseende og egenskaper av bare ben. Vi har gjennomgått lerretskoordinatsystemet, rektangulære gjengivelsesmetoder, noe greit datautvinning ved hjelp av jQuery's medfødte awesomeness [Har jeg nevnt hvor mye jeg liker jQuery?], Så på hvordan etikettene er trukket, og endelig sett på logikken bak gjengivelsen av selve grafen.
På slutten av denne artikkelen bør utgangen se slik ut.
Neste!
Vår nåværende gjennomføring er ganske mangelfull. Det ser blid ut, kan ikke opprette flere grafer på samme side, og la oss innse det, er ganske spartansk på funksjonens front. Vi skal takle alt det neste uke. I neste artikkel vil vi:
- Refactor vår kode mot å gjøre det til en fullverdig jQuery-plugin.
- Legg litt øye snus.
- Ta med noen flotte små funksjoner.
Spørsmål? Kritikk? Ros? Du er velkommen til å treffe kommentarene. Takk for at du leser, og når du er klar, gå videre til del to!
- Følg oss på Twitter, eller abonner på NETTUTS RSS Feed for flere daglige webutviklingsverktøy og artikler.