Bygg et lærredbildeditor med lerret

Vi kommer ikke til å bli vill med det, det er bare ikke tid, men vi vil se hvor lett det er å gjøre ting som å rotere, endre størrelse, oversette og til og med subtil fargemanipulering. Ikke bry deg selv om at vi vil fullføre med et lik Photoshop, selv om det er teoretisk mulig, men vurderer at vi jobber innenfor begrensninger av ingenting mer komplekst enn en nettleser, personlig tror jeg fortsatt det er ganske bemerkelsesverdig.

Denne opplæringen inneholder en screencast tilgjengelig for Tuts + Premium medlemmer.


Hva du trenger for denne opplæringen

For å lage en fungerende versjon av demoen lokalt må du bruke en webkitbasert nettleser som Safari eller Chrome eller Opera. Demoen vil fungere i Firefox, men det må bli kjørt gjennom en webserver for det meste av funksjonaliteten til arbeid. Ikke engang tenk på å bruke IE; bare versjon 9 nærmer seg støtte for lerretelementet, og for å være ærlig, ville jeg ikke engang stole på at IE9 skulle gjengi koden og funksjonaliteten på riktig måte.


Starter

Den underliggende HTML er egentlig ganske triviell; alt vi trenger for strukturen til redaktøren er følgende grunnleggende elementer:

    Kanin bilde editor     
Lagre Rotate Venstre Rotere Høyre Endre størrelse B & W Sepia

Lagre siden som image-editor.html. Bortsett fra de vanlige HTML-elementene som utgjør skjelettet på siden, har vi et tilpasset stilark, som vi legger til i et øyeblikk, og et stilark levert av jQuery UI. På bunnen av siden, like før avslutningen tag, vi har en referanse til jQuery (nåværende versjon på tidspunktet for skriving er 1.4.4), en referanse til jQuery UI (gjeldende versjon 1.8.7) og et tomt skript tag som vi skal sette koden til gir redaktøren sin funksjonalitet.

De jQuery-brukergrensesnittkomponentene vi skal bruke i dette eksemplet, er resizable og dialog, og temaet er ui-lightness.

De synlige elementene på siden er ganske grunnleggende; Vi har en ytre som inneholder

elementet, innenfor som bor to
elementer. Den første inneholder element som vi skal bruke til å manipulere bildet vårt. Den andre inneholder en verktøylinje med knapper som vil bli brukt til å gjøre manipulasjonene. Fra id attributter gitt til hver knapp, bør det være ganske åpenbart hva hver knapp gjør.


Legge til stilene

Som HTML, er CSS brukt ekstremt enkelt, og består av følgende:

#imageEditor width: 482px; margin: auto; padding: 20 piksler; grense: 1px solid # 4b4b4b; -moz-border-radius: 8 piksler; -webkit-border-radius: 8 piksler; border-radius: 8 piksler; background-color: #ababab;  #editorContainer display: block; bredde: 480px; høyde: 480px;  #editor display: block; margin: 0 20px 20px 0; grense: 1px solid # 4b4b4b;  #toolbar display: block; margin: 20px 0 0;  #toolbar en margin-right: 10px; skissere: none; color: # 4b4b4b;  #resizer border: 2px dashed # 000;  #tip padding: 5px; margin: 0; grense: 1px solid # 000; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; stilling: absolutt; background-color: #fff; bakgrunnsfarge: RGBA (255,255,255, 0,3); -moz-boks-skygge: 1px 1px 1px rgba (0,0,0,0,5); -webkit-boks-skygge: 1px 1px 1px rgba (0,0,0,0,5); boks-skygge: 1px 1px 1px rgba (0,0,0,0,5); 

Lagre dette som image-editor.css i samme katalog som HTML-siden. Det er ikke noe virkelig bemerkelsesverdig her, for det meste stilene oppsettet redaktøren og dens bestanddeler på den måten som er illustrert i bildet nedenfor:



Full Screencast



Den morsomme delen

Alt som er igjen å gjøre er å legge til koden som gjør at redaktøren jobber. Begynn med å legge til koden nedenfor til den tomme > element nederst på siden:

(funksjon ($) // få lerret og kontekst var editor = document.getElementById ("editor"), kontekst = editor.getContext ("2d"), // lage / laste bildebilde = $ ("", src:" img / graffiti.png ", last: funksjon () context.drawImage (dette, 0, 0);), // mer kode å følge her?) (jQuery);

Først og fremst plasserer vi all vår kode i et lukket og aliasing av jQuery-objektet som $ karakter. Jeg skjønner at jQuery aliaserer seg automatisk til $ tegn for oss, men det er situasjoner der dette kan føre til konflikter med annen kode som kan være i bruk når vår kode blir implementert av andre.

Dette er også den anbefalte måten å lage plugins, slik at du bare gjør dette hver gang jQuery brukes, gjør det mye raskere og enklere å gå tilbake og slå koden til et plugin hvis det er nødvendig. Jeg finner det enklere å skrive all min jQuery-kode i et lukning som dette. Det har også andre fordeler, for eksempel å fjerne en avhengighet av globale variabler - alle variablene vi oppretter, blir trygt skjult fra andre koden utenom lukkingen i de fleste tilfeller.

For å jobbe med lerretet må vi få en referanse til konteksten. Dette er et objekt som representerer overflaten av lerretet på hvilket mest av metodene for å arbeide med lerretet kalles. Et par metoder kan kalles på lerretobjektet direkte, men de fleste kalles på kontekstobjektet.

Å få sammenhengen er en to-trinns prosess; Vi får først en referanse til elementet selv bruker standard JavaScript document.getElementById () metode, vi kaller da getContext () metode på lerretet (dette er en slik metode som kan kalles direkte på lerretelementet, og med god grunn!), som spesifiserer 2d som konteksten. For tiden er 2d den eneste konteksten som i stor grad eksisterer, selv om vi i fremtiden kan se frem til å jobbe med 3d-sammenhenger.

Både lerret- og kontekstavobjektene lagres i variabler på toppnivå (ekvivalenten av globale variabler var vi ikke arbeider innenfor en nedleggelse) slik at alle funksjoner vi definerer kan bruke dem.

Etter disse to variablene oppretter vi en annen, kalt bilde. Vi bruker jQuery her for raskt og enkelt å lage et nytt bildeelement. Vi satte src av et bilde (et eksempel, royaltyfritt bilde er inkludert i koden nedlasting) slik at vi har noe å jobbe med, og legg til en på Last hendelsehandler som bare maler bildet på lerretet et bildet har lastet inn. Det er viktig når du arbeider med lerretet for å sikre at noen brukte bilder er fullt lastet før de legges til lerretet.

Bildet er malt på lerretet ved hjelp av drawImage () metode, som kalles på kontekst gjenstand. Denne metoden tar tre argumenter (det kan eventuelt ta mer, som vi skal se senere i eksemplet); Disse argumentene er bildet du skal bruke (referert til ved hjelp av dette søkeord), x posisjon på lerretet for å begynne å tegne bildet, og y posisjon på lerretet for å begynne å tegne bildet. Prøvebildet er den eksakte størrelsen på lerretet i dette eksemplet, og for enkelhet er det helt firkantet.

Vi er nå klare til å legge til noe mer kode på dette stadiet. Det er et etterkommet komma etter bildet vi opprettet, så neste koden vi legger til, vil også være en variabel.


Legger til verktøylinjefunksjonalitet

Deretter må vi legge til noen kode for å håndtere knappene på verktøylinjen. Vi kan bare legge til en rekke klikkbehandlere, en for hver knapp som vi ønsker å legge til. Selv om det er lett å gjøre, ville det ikke være svært effektivt og ville ikke skalere utrolig bra.

Ideelt sett ønsker vi en enkelt mesterfunksjon som håndterer et klikk på en hvilken som helst knapp og påberoper den riktige funksjonen. Heldigvis er dette også veldig enkelt. Legg til følgende kode direkte etter bildet vi nettopp opprettet:

// verktøylinje funksjoner verktøy = ; $ ("# verktøylinje"). barn (). klikk (funksjon (e) e.preventDefault (); // ring de aktuelle funksjonsverktøyene [this.id] .call (this););

Det er så enkelt. La oss dekke hva denne koden gjør. Den siste toppnivåvariabelen vi oppretter, kalles verktøy og den inneholder et tomt objekt (på dette stadiet). Funksjonene for hver enkelt knapp vil bli lagt inn i dette objektet, som vi ser snart.

Vi legger til en enkelt klikk handler, festet til alle barn av elementet med id verktøylinje (en av

elementer i den underliggende HTML).

Innenfor denne klikkhåndteringsfunksjonen stopper vi først standardoppførselen til nettleseren, som ville være å følge linken (dette forhindrer at uønsket "jump-to-top" -adferd noen ganger vises når du bruker standard elementer som knapper).

Til slutt bruker vi JavaScript anrop() metode til funksjonen i eiendommen til verktøy objekt som samsvarer med id Attributt av lenken som ble klikket. Som alt vi trenger fra koblingen som ble klikket, er det id attributt, vi kan bruke standarden dette søkeord uten å pakke det inn i et jQuery-objekt. De anrop() Metode krever at dette Søkeordet er også overført til det som et argument.

Nå, hvis vi legger til en funksjon i verktøyobjektet under eiendommen lagre, når vi klikker på verktøylinjeknappen med id lagre, vil funksjonen bli kalt. Så alt vi trenger å gjøre nå er å legge til en funksjon for hver av verktøylinjeknappene våre.


Lagrer det redigerte bildet

Vi starter med lagringsfunksjonen, da den er ganske liten og enkel. Legg til følgende kode i verktøy gjenstand:

// utdata til  lagre: funksjon () var saveDialog = $ ("
") .appendTo (" body "); $ ("", src: editor.toDataURL ()). appendTo (saveDialog); saveDialog.dialog (resizable: false, modal: true, title:" Høyreklikk og velg "Lagre bilde som", bredde: editor. bredde + 35);,

Det første som vår funksjon gjør er å lage en ny

element og legg det til av siden. Dette elementet vil bli brukt sammen med jQuery UIs dialogkomponent for å lage en modal dialogboks.

Deretter lager vi et nytt bildeelement; denne gangen har vi satt det src til en base-64 kodet representasjon av alt som finnes i lerretet. Denne handlingen utføres ved hjelp av toDataURL () metode, som for øvrig er en annen metode som kalles direkte på lerretelementet. Når bildet er opprettet, legges det til bildet

element opprettet i forrige trinn.

Endelig initialiserer vi dialogkomponenten; dette gjøres ved hjelp av dialog () metode, en metode lagt til av jQuery UI. En gjenstand bokstavelig er sendt til dialog () metode som gjør at vi kan angi forskjellige konfigurasjonsalternativer. I dette tilfellet konfigurerer vi dialogen slik at den ikke kan resizable og slik at den er modal (et overlegg vil bli brukt på resten av siden mens dialogen er åpen). Vi stiller også tittelen på dialogboksen til en streng som gir instruksjoner om hva du skal gjøre for å lagre objektet, og gjør dialogboksen stor nok til å inneholde bildet ved å sette bredden til bredden på lerretelementet pluss 35 piksler.


rotasjon

Et vanlig trekk ved bildeditorer er muligheten til å rotere et element, og det er ganske enkelt å implementere dette i redaktøren ved hjelp av innebygd lerretsfunksjon. Legg til følgende funksjoner etter lagringsfunksjonen:

roter: funksjon (conf) // lagre gjeldende bilde før du roterer $ ("", src: editor.toDataURL (), last: funksjon () // roter lerret context.clearRect (0, 0, editor.width, editor.height); context.translate (conf.x, conf.y) ; context.rotate (conf.r); // redraw lagret bilde context.drawImage (dette, 0, 0);;, rotateL: function () var conf = x: 0, y: editor. høyde, r: -90 * Math.PI / 180; tools.rotate (conf);, rotereR: funksjon () var conf = x: editor.width, y: 0, r: 90 * Math.PI / 180; tools.rotate (conf);,

Så vi har lagt til tre nye funksjoner; en master rotere funksjon, og deretter en funksjon hver for å rotere til venstre og rotere høyre verktøylinjeknapper. De rotateL () og rotateR () Fungerer hver bare bygge et egendefinert konfigurasjonsobjekt og ring deretter masteren rotere() funksjon, passerer i konfigurasjonsobjektet. Det er mesteren rotere() funksjon som faktisk utfører rotasjonen. Et viktig poeng å merke seg er at det er selve lerretet vi roterer, ikke bildet på lerretet.

Konfigurasjonsobjektet vi lager i rotateL () og rotateR () funksjoner er veldig enkle; den inneholder tre egenskaper - x, y og r. Egenskapene x og y referer til mengden oversettelse som kreves og r er mengden rotasjon. Hvert klikk på en roterende knapp vil rotere bildet med pluss eller minus 90 grader.

I rotateL () funksjon må vi oversette lerretet på samme avstand som lerretets høyde på den vertikale aksen for å sikre at bildet forblir synlig når lerretet har blitt rotert. Rotasjon til "venstre" er klassifisert som negativ rotasjon som den er mot klokken. Når vi beregner rotasjonsvinkelen, kan vi ikke bruke grader, vi må konvertere 90 grader (eller -90 grader i dette tilfellet) til radianer. Dette er enkelt og krever følgende formel:

Antall grader multiplisert med Pi delt med 180

De rotateR () funksjonen er like rett frem, denne gangen oversetter vi lerretet på den horisontale akse i stedet for den vertikale akse og bruker et positivt tall for rotasjon i retning med urviseren.

I mesteren rotere() funksjon vi trenger igjen å ta en kopi av det nåværende bildet på lerretet, som vi gjør ved å lage et nytt bildeelement med jQuery og sette dens src til resultatet av toDataURL () metode igjen. Denne gangen ønsker vi å tegne bildet tilbake til lerretet når lerretet har blitt rotert, slik at vi legger til et på Last hendelseshåndterer til bildet.

Når bildet er lastet, fjerner vi først lerretet ved hjelp av clearRect () metode. Denne metoden tar fire argumenter; De to første argumentene er x og y koordinater for å begynne å rydde. Tredje og fjerde er størrelsen på området for å rydde. Vi ønsker å rydde hele lerretet slik at vi starter ved 0,0 (det øverste venstre hjørnet av lerretet) og fjern hele bredden og høyden på lerretet.

Når vi har fjernet lerretet, oversetter vi det (flytt det i hovedsak) ved hjelp av oversette() transformasjonsmetode. Vi vil oversette den enten den fulle høyden, av hele lerretets bredde, avhengig av om rotateL () eller rotateR () funksjonen startet rotasjonen. Det er nødvendig å oversette lerretet fordi standard rotasjon skjer rundt nederst til høyre på lerretet, ikke i midten som du forventer.

Vi kan så rotere lerretet og deretter trekke bildet tilbake på lerretet. Selv om vi tegner det samme bildet tilbake til lerretet, har lerret blitt rotert, slik at bildet automatisk blir rotert også. Igjen kan vi referere til bildet som skal overføres til drawImage () metode som dette fordi vi er inne i lastbehandleren for bildet og jQuery sikrer at dette refererer til bildet. Neste skjermbilde viser bildet rotert til venstre en gang:



Endre størrelse på bildet

Å endre størrelse på bildet er vårt mest komplekse samspill, og funksjonen som kreves for å gjøre det, er ganske stor, selv om størrelsen på lerretet selv er ganske trivielt. Legg til følgende funksjon i verktøyobjektet etter rotasjonsfunksjonene vi nettopp så på:

endre størrelse: funksjon () // opprett resizable over lerret var koordinater = $ (editor). offset (), resizer = $ ("
", id:" resizer "). css (posisjon:" absolutt ", venstre: koords.left, topp: koord.top, bredde: editor.width - 1, høyde: editor.height - 1). appendTo ("body"); var resizeWidth = null, resizeHeight = null, xpos = editor.offsetLeft + 5, ypos = editor.offsetTop + 5; resizer.resizable (aspektRatio: true, maxWidth: editor.width - 1, maxHeight : editor.height - 1, resize: funksjon (e, ui) resizeWidth = Math.round (ui.size.width); resizeHeight = Math.round (ui.size.height); // verktøytips for å vise ny størrelse var string = "Ny bredde:" + resizeWidth + "px,
ny høyde: "+ resizeHeight +" px ", hvis ($ (" # tips "). lengde) $ (" # tips "). html (streng); else var tip = $ : "tip", html: streng). css (venstre: xpos, topp: ypos). appendTo ("body");, stopp: funksjon (e, ui) // bekreft resize det var confirmDialog = $ ("
", html:" Bildet blir endret til "+ resizeWidth +" px wide, og "+ resizeHeight +" px high.
Fortsett? "); // init bekreft dialogboksen confirmDialog.dialog (resizable: false, modal: true, title:" Bekreft resize? ", Knapper: Cancel: function () // rydde opp $ (dette). dialog ("lukk"); resizer.remove (); $ ("# tip"). fjerne ();, ja: funksjon () // rydde opp $ (dette) .dialog ("close"); resizer .remove (); $ ("# tip"). fjern (); $ ("", src: editor.toDataURL (), last: funksjon () // fjern gammel bilde context.clearRect (0, 0, editor.width, editor.height); // endre størrelsen på canvas editor.width = resizeWidth; .height = resizeHeight; // redraw lagret bilde context.drawImage (dette, 0, 0, resizeWidth, resizeHeight);;););,

Så la oss se trinnene som kreves av vår resize-funksjon. Først trenger vi noen måte å indikere til brukeren hvilken størrelse bildet skal resizes til, og brukeren krever noen måte å sette inn den nye størrelsen på. Vi vil da bekrefte om brukeren ønsker å bruke den nye størrelsen, og deretter i så fall, bruk den nye størrelsen. Den nye funksjonen gjør alle tingene, la oss se hvordan.

Først får vi koordinatene på siden av lerretelementet ved hjelp av jQuery offset () metode, slik at vi vet hvor du skal plassere det resizable elementet. Vi lager deretter en ny

element, som vil bli resizable, og gi det et id av endre størrelse på slik at vi lett kan referere til det. Vi stiller også noen stilegenskaper til det nye elementet for å plassere det over lerretet. Når disse stilene er satt, legger vi det til av siden. Resizable vil vises som en prikket kant rundt innsiden av lerretet, som vist nedenfor:


Deretter initialiserer vi to variabler, men setter deres verdier til null for tiden. Disse brukes til å lagre bredden og høyden som resizable er endret til når den er endret. Disse variablene vil bli fylt og brukt senere i funksjonen. De XPOS og ypos Variabler brukes til å plassere et verktøytips som vi oppretter i et øyeblikk. De plasserer verktøytipset 5 piksler fra venstre kant og toppkanten av lerretet.

Deretter initialiserer vi resizable ved hjelp av jQuery brukergrensesnitt skalerbar () metode. Vi konfigurerer resizable for å få sitt aspektforhold låst; bildet vårt er firkantet, så vi vil at det skal forbli firkantet, uansett størrelse det er endret til. Vi sikrer også at bildet ikke kan økes i størrelse slik at kvaliteten på bildet blir beholdt. Hvis bildet ble forstørret i stedet for å bli krympet, ville det bli blokkert. De maxWidth og maxHeight Konfigurasjonsalternativene sikrer at bildet bare kan gjøres mindre. Begge er satt til henholdsvis bredde og høyde på lerretet.

Den resizable komponenten har noen tilpassede hendelseshåndterere som vi kan tilordne funksjoner som vil bli utført når disse tilpassede hendelsene blir sparket. Vi bruker to av disse hendelsesbehandlerne for dette eksempelet; endre størrelse på, som vil bli avfyrt hver gang resizable er endret, og Stoppe som avfyres når resizable er ferdig med å bli omformet.

Funksjonen for å endre størrelse kan motta to argumenter; Den første er et hendelsesobjekt, som vi ikke trenger å bruke i dette eksemplet, men som må deklareres for å kunne benytte seg av det andre argumentet, som vi trenger. Det andre argumentet er et objekt som inneholder nyttig informasjon om resizable, inkludert størrelsen den er blitt endret til. Det første vi gjør i denne funksjonen, er å tilordne den nye størrelsen på resizable til vår resizeWidth og resizeHeight variabler ved hjelp av egenskapene til ui protester mot at funksjonen mottar.

Det siste som denne funksjonen gjør er å opprette verktøytipset som forteller brukeren hvor stor resizable som er for øyeblikket. Hvis dette verktøytipset allerede eksisterer, trenger vi ikke å gjenskape det og kan bare sette sin indre tekst til en streng som viser gjeldende størrelse på resizable. Hvis verktøytipset ikke allerede eksisterer, for eksempel første gang resizable er endret, oppretter vi det fra grunnen av. Verktøytipset er plassert ved hjelp av XPOS og ypos som vi opprettet tidligere. Strengen er bygget fra begynnelsen hver gang resizable endrer størrelsen. Verktøytipset vil se slik ut:


Stopp-funksjonen, som utføres en gang når resize-interaksjonen avsluttes, oppretter først et nytt dialogelement som kontrollerer at den besøkende vil bruke den nye størrelsen på lerretet. Enda en gang er dialogboksen konfigurert slik at den ikke kan resizable seg selv og slik at den er modal. Vi legger også til noen knapper til denne dialogen. Den første er a Avbryt knappen, som gjør det mulig for besøkende å gå ut av resize-operasjonen uten å bruke den nye størrelsen. Alt vi gjør her er litt housekeeping, fjerner dialogboksen, resizable og verktøytipset.

Vi lager også en Ja knappen som gjelder den nye størrelsen. Vi gjør også de samme husholdningsoppgaver her, men da bruker vi den nye størrelsen vi oppretter et nytt bilde en gang til på samme måte som vi har gjort flere ganger allerede. Det er ekstremt enkelt å sette inn den nye størrelsen på lerretet. Vi leverer bare verdiene som resizable ble endret til bredden og høydeegenskapene til lerretelementet. Her er dialogboksen, som fremstår som den samme som lagringsdialogen fra tidligere, bare med annet innhold:



Endre rgb-verdiene for individuelle piksler

Jeg sa tidligere at vi har fullstendig pikselnivåkontroll av innholdet i lerretelementet, slik at våre to siste verktøylinjeknappfunksjoner vil gjøre akkurat det. Den første funksjonen brukes til å konvertere bildet til gråtoner, den andre endrer bildet til sepia tone. Vi ser først på gråtoner-funksjonen:

gråtoner: funksjon () // få bildedata var imgData = context.getImageData (0, 0, editor.width, editor.height), pxData = imgData.data, lengde = pxData.length; for (var x = 0; x < length; x+=4)  //convert to grayscale var r = pxData[x], g = pxData[x + 1], b = pxData[x + 2], grey = r * .3 + g * .59 + b * .11; pxData[x] = grey; pxData[x + 1] = grey; pxData[x + 2] = grey;  //paint grayscale image back context.putImageData(imgData, 0, 0); ,

Det første som denne funksjonen må gjøre er å få de nåværende pikseldataene på lerretet. Vi bruker getImageData () metode for å gjøre dette. Denne metoden godtar fire argumenter, som er de samme som clearRect () Metode som vi så på tidligere - de to første argumentene er x og y posisjoner for å begynne å samle data fra og den tredje og fjerde er bredden og høyden av området for å få. Vi ønsker hele lerretet slik at vi starter ved 0,0 (øverst til venstre) og fortsetter for bredde og høyde på lerretet. Den resulterende gjenstanden returnert med metoden er lagret i imgData variabel.

Objektet som er lagret i denne variabelen, har en eiendom som kalles data; innenfor denne egenskapen er en matrise som inneholder r g b og alfa verdier for hver enkelt piksel i lerretet, så det første elementet i arrayet vil inneholde r verdien av den første piksel, det andre elementet inneholder g verdien av den første piksel, den tredje inneholder b verdien av den første piksel, og den fjerde gjenstanden inneholder alfaværdien til knyttnepikselen. Denne serien er utrolig stor; en 480 x 480 pixel bilde inneholder 230400 piksler og vi har fire elementer for hver enkelt pixel. Dette gjør arrayet totalt 921600 varer i lengden! Denne lengden lagres også for bruk i til sløyfe som vi definerer neste.

For-sløyfen er litt annerledes enn vanlig for sløyfer. Husk at arrayet kan organiseres i diskrete blokker med 4 elementer, hvor hvert element i en enkelt blokk refererer til de enkelte rgba-komponentene, så vi slår gjennom gruppen fire elementer om gangen. På hver iterasjon får vi hver pikselkomponent og bruker deretter formelen r * .3 + g * .59 + b * .11 å konvertere hver til gråtoner. Vi lagrer deretter den konverterte pixelkomponenten tilbake til sin opprinnelige matrise.

Når vi har slått over hele oppstillingen, kan vi skrive arrayinnholdet tilbake til lerretet, erstatte hver originalpiksel med sin nye gråtoner-motpart ved hjelp av putImageData () metode, som ganske enkelt gjør det motsatte av getImageData ().

Sepia-tone-funksjonen er identisk med gråskala-funksjonen, bortsett fra at vi bruker en annen formel for å konvertere hver r g b komponent til sepia tone:

sepia: funksjon () // få bilde data var imgData = context.getImageData (0, 0, editor.width, editor.height), pxData = imgData.data, lengde = pxData.length; for (var x = 0; x < length; x+=4)  //convert to grayscale var r = pxData[x], g = pxData[x + 1], b = pxData[x + 2], sepiaR = r * .393 + g * .769 + b * .189, sepiaG = r * .349 + g * .686 + b * .168, sepiaB = r * .272 + g * .534 + b * .131; pxData[x] = sepiaR; pxData[x + 1] = sepiaG; pxData[x + 2] = sepiaB;  //paint sepia image back context.putImageData(imgData, 0, 0); 

Her er et bilde av bildet når det er blitt konvertert til sepia tone:



Konklusjon

I denne opplæringen har vi sett hvordan lerretet kan omdannes til et kraftig bilderedigeringsprogram som gir oss noen av funksjonene til de grunnleggende applikasjonsbaserte bildeditorene som vi er kjent med. Dette eksempelet kan enkelt utvides for å legge til andre funksjoner, for eksempel beskjæring og tegning med et blyantverktøy, selv om jeg vil legge til tillegget av denne funksjonaliteten til deg. Takk for at du leste.