Slik oppretter du en jQuery Image Cropping Plugin fra scratch - Del I

Webapplikasjoner må gi enkle å bruke løsninger for opplasting og manipulering av rikt innhold. Denne prosessen kan skape vanskeligheter for noen brukere som har minimal fotoredigering. Beskjæring er en av de mest brukte foto manipulasjonsteknikkene, og denne trinnvise opplæringen vil dekke hele utviklingsprosessen til et plugin for bildeoppskæring for jQuery JavaScript-biblioteket.


Trinn 1. Sette opp arbeidsområdet

Først skal vi sette opp vårt prosjekt arbeidsområde for denne opplæringen. Begynn med å opprette et hierarki med kataloger og tomme filer med navnet som eksemplifisert i bildet nedenfor:

Deretter må du laste ned jQuery JavaScript-biblioteket og plassere det inne i / ressurser / js / mappe. Bildet som brukes i denne opplæringen må være navngitt Example.jpg og plassert inne i / ressurser / images / mappe. Du kan bruke dette bildet (takket være gsso-lager), utstyrt med kildefilene til denne opplæringen, eller en av dine egne. Og den siste filen er outline.gif fil, som må plasseres inne i / Ressurser / js / imageCrop / mappe.


Trinn 2. Opprette testsiden

For å teste vår plugin må vi legge den til et bilde. Før vi begynner å jobbe med det, lager vi en enkel side som inneholder bildet.

HTML-koden

Åpne opp index.html filen i din favoritt tekstredigerer og skriv følgende kode.

     jQuery Image Cropping Plug-In       

jQuery Image Cropping Plug-In

jQuery Image Cropping Plug-In

Det er ikke noe fancy her: bare ren HTML-kode. Vi har lastet et stilark for siden, jQuery, våre plugin-filer (som for øyeblikket er tomme) og plassert et bilde inne i dokumentet.

CSS

Rediger nå style.css som vist ovenfor.

 * margin: 0; oversikt: 0; polstring: 0;  kropp bakgrunnsfarge: #ededed; farge: # 646464; font-familie: 'Verdana', 'Geneva', sans-serif; skriftstørrelse: 12px; tekstskygge: 0 1px 0 #ffffff;  h1 skriftstørrelse: 24px; font-weight: normal; margin: 0 0 10px 0;  div # wrapper margin: 25px 25px 25px 25px;  div.image-decorator -moz-border-radius: 5px 5px 5px 5px; -moz-box-shadow: 0 0 6px # c8c8c8; -webkit-grense-radius: 5px 5px 5px 5px; -webkit-boks-skygge: 0 0 6px # c8c8c8; bakgrunnsfarge: #ffffff; grense: 1px solid # c8c8c8; grense-radius: 5px 5px 5px 5px; bokseskygge: 0 0 6px # c8c8c8; display: inline-block; høyde: 360px; polstring: 5px 5px 5px 5px; bredde: 480px; 

Vi har tilpasset aspektet av siden vår ved å endre bakgrunnsfargen og legge til noen grunnleggende styling til tittelen og bildet.


Trinn 3. Skrive en grunnleggende jQuery-plugin

La oss begynne med å opprette en grunnleggende jQuery-plugin-modul.

"Lær mer om hvordan du skriver din egen plug-in, via dette innlegget. Det beskriver grunnleggende, beste praksis og vanlige fallgruver for å passe på når du begynner å skrive plugin-modulen din."

Åpen /resources/js/imageCrop/jquery.imagecrop.js og legg til følgende kode.

 // Plasser alltid en plugin i '(funksjon ($) // Plug-in går her) (jQuery);' (funksjon ($) $ .imageCrop = funksjon (objekt, customOptions) ; $ .fn.imageCrop = funksjon (customOptions) // Iterate over hver objekt this.each (function () var currentObject = dette bildet = nytt bilde (); // og legg til bildeCrop når objektet er lastet image.onload = function () $ .imageCrop (currentObject, customOptions);; // Tilbakestill src fordi ikke bufret bilder brann laster noen ganger bilde .src = currentObject.src;); // Med mindre plugin-modulen returnerer en egenverdi, må du alltid ha // funksjonen returnere "dette" søkeordet for å opprettholde kjedelighet returnere dette;;) (jQuery);

Vi har nettopp utvidet jQuery ved å legge til en ny funksjonsegenskap til jQuery.fn gjenstand. Nå har vi en veldig grunnleggende plugin-modul som detererer over hver gjenstand og legger til imageCrop når objektet er lastet. Legg merke til at de bufrete bildene ikke brann laste noen ganger, så vi tilbakestiller src attributt for å fikse dette problemet.


Trinn 4. Legge til tilpassbare alternativer

Tillat for tilpasningsalternativer gjør en plug-in langt mer fleksibel for brukeren.

 $ .imageCrop = funksjon (objekt, customOptions) // I stedet for å kreve en lang rekke argumenter, pass // plugin-alternativene i et objekt som er lettere som kan utvides over // pluginets standardinnstillinger var defaultOptions =  allowMove: true, allowResize: true, allowSelect: true, minSelect: [0, 0], outlineOpacity: 0.5, overlayOpacity: 0.5, selectionPosition: [0, 0], selectionWidth: 0, selectionHeight: 0; // Angi alternativer til standard var options = defaultOptions; // og fusjonere dem med de egendefinerte alternativene setOptions (customOptions); ; 

Vi har definert en matrise med standardvalgene, og slått dem sammen med de tilpassede alternativene ved å ringe setOptions funksjon. La oss gå videre og skrive kroppen til denne funksjonen.

? // Flett nåværende alternativer med den egendefinerte alternativfunksjonen setOptions (customOptions) options = $ .extend (alternativer, customOptions); ; 

De $ .Extend () funksjonen fusjonerer innholdet av to eller flere objekter sammen i det første objektet.

Alternativene

Følgende liste beskriver hvert valg av plugin-modulen.

  • allowMove - Angir om valget kan flyttes (standardverdien er ekte).
  • allowResize - Angir om valget kan endres (standardverdien er ekte).
  • allowSelect - Angir om brukeren kan lage et nytt valg (standardverdien er ekte).
  • minSelect - Minste arealstørrelse for å registrere et nytt utvalg (standardverdien er [0, 0]).
  • outlineOpacity - Konturens opasitet (standardverdien er 0.5).
  • overlayOpacity - Overlay-opaciteten (standardverdien er 0.5).
  • selectionPosition - Utvalgsposisjonen (standardverdien er [0, 0]).
  • selectionWidth - Valgbredden (standardverdien er 0).
  • selectionHeight - Valghøyden (standardverdien er 0).

Trinn 5. Sette opp lagene

På dette trinnet endrer vi DOM for å bli forberedt på det neste trinnet: Plugin-grensesnittet.

Først vil vi initialisere bildelaget.

? // Initialiser bildet laget var $ image = $ (objekt); 

Start nå en bildeholder.

? // Initialiser en bildeholder var $ holder = $ ('
') .css (posisjon:' relative '). bredde ($ image.width ()) .height ($ image.height ()); // Vri holderen rundt bildet $ image.wrap ($ holder) .css (posisjon: 'absolutt');

Som du kan se har holderlaget samme størrelse som bildet og en relativ posisjon. Deretter kaller vi .pakke inn() funksjon for å plassere bildet inne i holderen.

Over bildet vil være overlegget laget.

? // Initialiser et overleggslag og legg det over bildet var $ overlay = $ ('
') .css (opacity: options.overlayOpacity, posisjon:' absolute ') .width ($ image.width ()) .height ($ image.height ()) .insertAfter ($ image);

Dette laget har samme størrelse som bildet, men har også fått absolutt posisjonering. Vi får verdien for opaciteten fra options.overlayOpacity og la jQuery bruke det. Dette elementet har også et ID, slik at vi kan endre egenskapene sine gjennom plugin-modulen. På bunnen kalles vi .insertAfter () Metode for å plassere overleggslaget rett etter bildet.

Det neste laget er utløserskiktet; Vi legger det etter overlegget, akkurat som vi gjorde med de forrige.

? // Initialiser et utløserlag og legg det over overleggslaget var $ trigger = $ ('
') .css (backgroundColor:' # 000000 ', opacity: 0, posisjon:' absolute ') .width ($ image.width ()) .height ($ image.height ()) .insertAfter ($ overlay) ;

Bakgrunnsfargen spiller ingen rolle, men det må være annerledes enn gjennomsiktig (som er som standard). Dette laget er usynlig fra brukeren, men det vil håndtere noen hendelser.

Vi legger omrisslaget over triggerlaget.

? // Initialiser et omrisslag og legg det over utløserlaget var $ outline = $ ('
') .css (opacity: options.outlineOpacity, posisjon:' absolute ') .insertAfter ($ trigger);

Og til slutt det siste laget.

? // Initialiser et valglag og legg det over omrisslaget var $ $ = $ ('
') .css (bakgrunn:' url ('+ $ image.attr (' src ') +') no-repeat ', posisjon:' absolutt ') .insertAfter ($ disposisjon);

De .attr () metode returnerer verdien av et spesifisert attributt. Vi brukte det til å få bildet src, og sette det som bakgrunnen for valglaget.

Absolutt posisjonering inne i relativ posisjonering

Du kan kanskje allerede vite dette, men et element med en relativ posisjonering gir deg kontrollen til å helt plassere elementer inne i den. Det er derfor holderlaget har en relativ stilling og alle sine barn en absolutt posisjon.

En utmerket forklaring på dette trikset er dekket i denne artikkelen.


Trinn 6. Oppdatering av grensesnittet

Først vil vi initialisere noen variabler.

? // Initialisere globale variabler var selectionExists, selectionOffset = [0, 0], selectionOrigin = [0, 0]; 

De selectionExists vil informere oss om et valg eksisterer. De selectionOffset vil inneholde forskyvningen i forhold til bildetes opprinnelse, og selectionOrigin vil angi opprinnelsen til valget. Ting blir mye tydeligere etter noen få skritt.

Følgende betingelser kreves hvis valget eksisterer når plugin-modulen er lastet inn.

? // Bekreft om valgstørrelsen er større enn det minimum akseptert // og sett valgeksistensen tilsvarende hvis (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; ellers selectionExists = false; 

Neste vi ringer til updateInterface () Fungerer for første gang for å initialisere grensesnittet.

? // Ring funksjonen 'updateInterface' for første gang til // initialiser plugin-grensesnittoppdateringenInterface (); 

Vi skal snart skrive inn kroppen til denne funksjonen. Akkurat nå, la oss ta vare på vår første begivenhet.

? hvis (options.allowSelect) // Bind en hendelsesbehandler til "mousedown" -hendelsen av triggerlaget $ trigger.mousedown (setSelection); 

Vi ringer .mousedown () hvis options.allowSelect er ekte. Dette vil binde en hendelseshandler til mousedown hendelsen av utløserlaget. Så, hvis en bruker klikker på bildet, vil setSelection () vil bli påkalt.

? // Få dagens offset for en elementfunksjon getElementOffset (objekt) var offset = $ (objekt). Offset (); returnere [offset.left, offset.top]; ; // Få den nåværende museposisjonen i forhold til bildeposisjonen funksjon getMousePosition (event) var imageOffset = getElementOffset ($ image); var x = event.pageX - imageOffset [0], y = event.pageY - imageOffset [1]; x = (x < 0) ? 0 : (x > $ image.width ())? $ image.width (): x; y = (y < 0) ? 0 : (y > $ image.height ())? $ image.height (): y; returnere [x, y]; ; 

Den første funksjonen, getElementOffset (), returnerer venstre og øverste koordinater for det angitte objektet i forhold til dokumentet. Vi har hentet denne verdien ved å ringe .offset () metode. Den andre funksjonen, getMousePosition (), returnerer gjeldende musposisjon, men i forhold til bildeposisjonen. Så, vi vil arbeide med verdier som bare er mellom 0 og bildebredden / høyden på henholdsvis x / y-aksen.

La oss skrive en funksjon for å oppdatere lagene våre.

? // Oppdater overleggslagsfunksjonen updateOverlayLayer () $ overlay.css (display: selectionExists? 'Blokk': 'ingen'); ; 

Denne funksjonen kontrollerer verdien av selectionExists variabel, og bestemmer om overlagslaget skal vises eller ikke.

? // Oppdater triggerskapsfunksjonen updateTriggerLayer () $ trigger.css (cursor: options.allowSelect? 'Crosshair': 'default'); ; 

De updateTriggerLayer () funksjonen endrer markøren til trådkors eller misligholde, avhengig av options.allowSelect verdi.

Deretter skriver vi updateSelection () funksjon. Det vil ikke bare oppdatere utvalgslaget, men også skisselaget.

? // Oppdater seleksjonsfunksjonen updateSelection () // Oppdatér oversiktslaget $ outline.css (cursor: 'default', display: selectionExists? 'Block': 'ingen', venstre: options.selectionPosition [0], top : options.selectionPosition [1]) .width (options.selectionWidth) .height (options.selectionHeight); // Oppdatér valglaget $ selection.css (backgroundPosition: (- options.selectionPosition [0] - 1) + 'px' + (- options.selectionPosition [1] - 1) + 'px', markør: alternativer. allowMove? 'move': 'default', display: selectionExists? 'block': 'ingen', venstre: options.selectionPosition [0] + 1, top: options.selectionPosition [1] + 1) .width .selectionWidth - 2> 0)? (options.selectionWidth - 2): 0) .height ((options.selectionHeight - 2> 0)? (options.selectionHeight - 2): 0); ; 

Først angir denne funksjonen egenskapene til omrisslaget: markøren, skjermen, størrelsen og dens posisjon. Neste kommer valglaget; Den nye verdien av bakgrunnsposisjonen vil gjøre bildene overlappende sømløst.

Nå trenger vi en funksjon for å oppdatere markøren når det er nødvendig. For eksempel, når vi foretar et valg, vil vi at markøren skal forbli a trådkors uansett hvilket lag vi er over.

? // Oppdater markørtypefunksjonen oppdateringCursor (cursorType) $ trigger.css (cursor: cursorType); $ outline.css (cursor: cursorType); $ selection.css (cursor: cursorType); ; 

Ja, det er så enkelt som det ser ut. Bare endre markør typen til den angitte!

Og nå, den siste funksjonen i dette trinnet; Vi trenger det for å oppdatere plugin-grensesnittet i forskjellige situasjoner - ved å velge, endre størrelsen på utgivelsen, og selv når plugin-modulen initialiserer.

? // Oppdater pluginens grensesnittfunksjonoppdateringInterface (sender) switch (sender) case 'setSelection': updateOverlayLayer (); updateSelection (); gå i stykker; case 'resizeSelection': updateSelection (); updateCursor ( 'trådkors'); gå i stykker; standard: updateTriggerLayer (); updateOverlayLayer (); updateSelection (); ; 

Som du kan se, er updateInterface () funksjonen filtrerer noen tilfeller og kaller de nødvendige funksjonene vi nettopp har skrevet.


Trinn 7. Innstilling av valget

Frem til nå tok vi vare på tilpasningsalternativene og grensesnittet, men ingenting knyttet til hvordan brukeren samhandler med plugin-modulen. La oss skrive en funksjon som setter et nytt utvalg når bildet klikkes.

? // Sett inn en ny valgfunksjon setSelection (event) // Forhindre standard handling av hendelsen event.preventDefault (); // Forhindre at hendelsen blir varslet event.stopPropagation (); // Bind en hendelseshandler til 'mousemove' og 'mouseup'-hendelsene $ (dokument) .mousemove (resizeSelection) .mouseup (releaseSelection); // Gi beskjed om at et valg eksisterer selectionExists = true; // Tilbakestill valgstørrelsen options.selectionWidth = 0; options.selectionHeight = 0; // Få valget opprinnelsesvalgOrigin = getMousePosition (hendelse); // Og sett sin posisjon options.selectionPosition [0] = selectionOrigin [0]; options.selectionPosition [1] = selectionOrigin [1]; // Oppdater bare de nødvendige elementene i plugin-grensesnittet // ved å angi avsenderen av gjeldende anropsoppdateringInterface ('setSelection'); ; 

Først setSelection funksjonen kaller to metoder: event.preventDefault () og event.stopPropagation (). Dette forhindrer at standardhandling og eventuelle foreldrehåndterere blir varslet om hendelsen. De .mousemove () Metoden binder en hendelseshandler til mousemove begivenhet. Dette vil ringe til resizeSelection () Fungerer hver gang brukeren beveger musepekeren. For å varsle om at et nytt utvalg blir gjort, vil selectionExists variabel er laget ekte og utvelgelsesstørrelsen er satt til 0. Deretter får vi utvelgelsesopprinnelsen ved å ringe vår tidligere skrevet funksjon, getMousePosition (), og passere sin verdi til options.selectionPosition. Til slutt kaller vi updateInterface () funksjon for å oppdatere plugin-grensesnittet i henhold til endringene som er gjort.


Trinn 8. Endre størrelse på valget

I det forrige trinnet skrev vi en funksjon for å sette inn et nytt utvalg. La oss nå skrive en funksjon for å endre størrelsen på det aktuelle valget.

? // Endre størrelsen på gjeldende valgfunksjon resizeSelection (event) // Forhindre standard handling av hendelsen event.preventDefault (); // Forhindre at hendelsen blir varslet event.stopPropagation (); var mousePosition = getMousePosition (hendelse); // Få valgstørrelsen options.selectionWidth = mousePosition [0] - selectionOrigin [0]; options.selectionHeight = mousePosition [1] - selectionOrigin [1]; hvis (options.selectionWidth < 0)  options.selectionWidth = Math.abs(options.selectionWidth); options.selectionPosition[0] = selectionOrigin[0] - options.selectionWidth;  else options.selectionPosition[0] = selectionOrigin[0]; if (options.selectionHeight < 0)  options.selectionHeight = Math.abs(options.selectionHeight); options.selectionPosition[1] = selectionOrigin[1] - options.selectionHeight;  else options.selectionPosition[1] = selectionOrigin[1]; // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('resizeSelection'); ; 

For å endre størrelsen på valget, må vi hente den nåværende museposisjonen. Fordi den returnerte verdien er i forhold til bildestørrelsen, må vi bare ta vare på de negative verdiene. Det vil aldri overskride bildegrensene. Som du vet, kan vi ikke ha en negativ verdi for bredde eller høyde egenskaper av et element. For å løse dette, kaller vi Math.abs () for å få den absolutte verdien og deretter reposisjonerer vi utvalget.


Trinn 9. Slett utvalget

Og nå den endelige funksjonen:

? // Slett gjeldende utvalgsfunksjon releaseSelection (event) // Forhindre standard handling av hendelsen event.preventDefault (); // Forhindre at hendelsen blir varslet event.stopPropagation (); // Unbind hendelsesbehandleren til "mousemove" -hendelsen $ (dokument) .unbind ('mousemove'); // Unbind hendelsesbehandleren til 'mouseup'-hendelsen $ (dokument) .unbind (' mouseup '); // Oppdatér opprinnelsesvalgsvalgOrigin [0] = options.selectionPosition [0]; selectionOrigin [1] = options.selectionPosition [1]; // Bekreft om valgstørrelsen er større enn det minimum akseptert // og sett valgeksistensen tilsvarende hvis (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; ellers selectionExists = false; // Oppdater bare de nødvendige elementene i plugin-grensesnittet // ved å angi avsenderen av gjeldende anropsoppdateringInterface ('releaseSelection'); ; 

Når valget blir utgitt, vil releaseSelection () funksjon fjerner tidligere tilknyttede hendelsesbehandlere i setSelection () funksjon ved å ringe .frigi () metode. Deretter oppdaterer det valgopprinnelsen og tester minimumstørrelsen som er akseptert for at valget skal eksistere.

Nå er vi nesten klare. Lukk denne filen og forberede deg til neste trinn.


Trinn 10. Styling Plug-In

Åpne /resources/js/imageCrop/jquery.imagecrop.css stilark, og legg til følgende linjer.

 div # image-crop overlay bakgrunnsfarge: #ffffff; overløp: skjult;  div # image-crop-outline bakgrunn: #ffffff url ('outline.gif'); overløp: skjult; 

Det er ikke noe komplisert her; Vi har lagt til noen styling til overlegget og disposisjonslagene.


Trinn 11. Testing av det endelige resultatet

For å teste vår plugin, må vi legge den til et bilde. La oss gjøre det og redigere index.html side.

Åpne manus stikkord?

  

? og skriv følgende JavaScript-kode.

 $ (dokument) .ready (funksjon () $ ('img # eksempel'). imageCrop (overlayOpacity: 0.25);); 

Vi har knyttet vår plugin til bildeelementet med eksempel id, og sett noen tilpassede alternativer. Vi brukte .klar() Metode for å bestemme når DOM er fullt lastet.

Og det er det! Lagre filen og åpne nettleseren din for å teste den ut.


Hva blir det neste

Nå har vi et grunnleggende bildebeskjæring jQuery-plugin-modul som lar oss velge et område på et bilde. I neste veiledning legger vi til flere tilpasningsalternativer, bygger en forhåndsvisningsrude, skriver noen skript på server-siden for å beskjære bildet? og mye mer. Jeg håper du har hatt den tiden vi har brukt sammen og fant denne opplæringen til å være nyttig. Takk for at du leste!