Cum de a crea un plugin jQuery Cropping Plugin de la zero - Partea I

Aplicațiile Web trebuie să ofere soluții ușor de utilizat pentru încărcarea și manipularea conținutului bogat. Acest proces poate crea dificultăți pentru unii utilizatori care au abilități minime de editare a fotografiilor. Decuparea este una dintre cele mai utilizate tehnici de manipulare a fotografiilor, iar acest tutorial pas cu pas va acoperi întregul proces de dezvoltare a unui plug-in de decupare a imaginilor pentru biblioteca JavaScript jQuery.


Pasul 1. Configurarea spațiului de lucru

Mai întâi, vom crea un spațiu de lucru pentru acest tutorial. Începeți prin crearea unei ierarhii de directoare și a unor fișiere goale denumite exemplificate în imaginea de mai jos:

Apoi, va trebui să descărcați biblioteca jQuery JavaScript și să o plasați înăuntru / resurse / js / pliant. Imaginea folosită în acest tutorial trebuie să fie numită Exemplu.jpg și plasate în interiorul / resurse / images / pliant. Puteți utiliza această imagine (datorită gsso-stock), furnizate cu fișierele sursă ale acestui tutorial sau unul de-al tău. Ultimul fișier este outline.gif fișier, care trebuie să fie plasat în interiorul / Resurse / js / imageCrop / pliant.


Pasul 2. Crearea paginii de test

Pentru a testa pluginul nostru, va trebui să îl atașăm la o imagine. Înainte de a începe să lucrăm la aceasta, vom crea o pagină simplă care să conțină imaginea respectivă.

HTML-ul

Deschideți index.html fișier în editorul dvs. de text preferat și scrieți următorul cod.

     jQuery Image Cropping Plug-In       

jQuery Image Cropping Plug-In

jQuery Image Cropping Plug-In

Nu este nimic interesant aici: cod simplu HTML. Am încărcat o foaie de stil pentru pagină, jQuery, fișierele noastre plug-in (care sunt în prezent goale) și au plasat o imagine în interiorul documentului.

CSS

Acum editați style.css după cum se arată mai sus.

 * marja: 0; contur: 0; umplutura: 0;  body background-color: #ededed; culoare: # 646464; font-family: "Verdana", "Geneva", sans-serif; font-size: 12px; text-shadow: 0 1px 0 #ffffff;  h1 font-size: 24px; font-weight: normal; margine: 0 0 10px 0;  div # wrapper margine: 25px 25px 25px 25px;  div.image-decorator -moz-border-radius: 5px 5px 5px 5px; -moz-box-shadow: 0 0 6px # c8c8c8; -webkit-border-radius: 5px 5px 5px 5px; -webkit-box-shadow: 0 0 6px # c8c8c8; fundal-culoare: #ffffff; frontieră: 1px solid # c8c8c8; raza de graniță: 5px 5px 5px 5px; box-shadow: 0 0 6px # c8c8c8; afișare: inline-block; înălțime: 360px; umplutura: 5px 5px 5px 5px; lățime: 480px; 

Am personalizat aspectul paginii noastre schimbând culoarea de fundal și adăugând un anumit stil de bază pentru titlu și imagine.


Pasul 3. Scrierea unui plug-in de bază jQuery

Să începem prin crearea unui plug-in de bază jQuery.

"Aflați mai multe despre cum să vă scrieți propriul plug-in, prin intermediul acestui mesaj. Acesta descrie elementele de bază, cele mai bune practici și capcanele obișnuite de urmărit pentru că începeți să vă scrieți plug-in-ul".

Deschis /resources/js/imageCrop/jquery.imagecrop.js și adăugați următorul cod.

 // Întotdeauna înfășurați un plug-in în '(funcția ($) // Plug-in merge aici) (jQuery);' (functie ($) $ .imageCrop = functie (obiect, customOptions) ; $ .fn.imageCrop = function (customOptions) // Itera peste fiecare obiect this.each (function () var currentObject = = new Image (); // Și atașați imageCrop atunci când obiectul este încărcat image.onload = function () $ .imageCrop (currentObject, customOptions); // Resetare src deoarece imaginile memorate în cache nu incarca imaginile .src = currentObject.src;); // Cu excepția cazului în care pluginul întoarce o valoare intrinsecă, întotdeauna funcția // returnează cuvântul cheie "acest" pentru a menține întărirea greșelii;) (jQuery);

Am extins doar jQuery adăugând o nouă proprietate a funcției jQuery.fn obiect. Acum avem un plug-in foarte simplu care se repetă peste fiecare obiect și se atașează imageCrop când obiectul este încărcat. Rețineți că imaginile din cache nu se declanșează sarcină uneori, așa că resetăm src atribuiți pentru a remedia această problemă.


Pasul 4. Adăugarea de opțiuni personalizabile

Permiterea opțiunilor de personalizare face ca un plug-in să fie mult mai flexibil pentru utilizator.

 $ .imageCrop = functie (obiect, customOptions) // In loc de a cere o lunga cantitate de argumente, treci optiunile // plug-in intr-un obiect literal care poate fi extins peste // default-ul plug-in-ului var defaultOptions = AllowMove: true, allowResize: true, allowSelect: true, minSelect: [0, 0], outlineOpacitate: 0.5, overlayOpacitate: 0.5, selectionPosition: [0, 0], selectionWidth: 0, selectionHeight: 0; // Setați opțiunile la valorile implicite var = opțiuni default; // și să le îmbinați cu opțiunile personalizate setOptions (customOptions); ; 

Am definit o matrice cu opțiunile implicite, apoi le-am îmbinat cu opțiunile personalizate sunând la setOptions funcţie. Să mergem mai departe și să scriem corpul acestei funcții.

? // Mergeți opțiunile curente cu funcția de opțiune personalizată setOptions (customOptions) options = $ .extend (opțiuni, customOptions); ; 

$ .Extend () funcția combină conținutul a două sau mai multe obiecte împreună în primul obiect.

Opțiunile

Următoarea listă descrie fiecare opțiune a plug-in-ului.

  • allowMove - Specifică dacă selecția poate fi mutată (valoarea implicită este Adevărat).
  • allowResize - Specifică dacă selecția poate fi redimensionată (valoarea implicită este Adevărat).
  • allowSelect - Specifică dacă utilizatorul poate face o nouă selecție (valoarea implicită este Adevărat).
  • minSelect - Dimensiunea minimă a zonei pentru înregistrarea unei noi selecții (valoarea implicită este [0, 0]).
  • outlineOpacity - Opacitatea conturului (valoarea implicită este 0.5).
  • overlayOpacity - Opacitatea suprapusă (valoarea implicită este 0.5).
  • selectionPosition - Poziția de selecție (valoarea implicită este [0, 0]).
  • selectionWidth - Lățimea de selecție (valoarea implicită este 0).
  • selectionHeight - Înălțimea de selecție (valoarea implicită este 0).

Pasul 5. Configurarea straturilor

În acest pas, vom modifica DOM pentru a vă pregăti pentru următorul pas: interfața plug-in-ului.

În primul rând, vom inițializa stratul de imagine.

? // Inițializați stratul de imagine var $ image = $ (obiect); 

Acum inițializați un suport de imagine.

? // Inițializați un suport de imagine var $ holder = $ ('
') .css (poziție:' relativ ') .width ($ image.width ()) .height ($ image.height ()); // Înfășurați suportul în jurul imaginii $ image.wrap ($ holder) .css (position: 'absolute');

După cum puteți vedea, stratul suport are aceeași dimensiune ca imaginea și o poziție relativă. Apoi, numim .înfășurați () pentru a plasa imaginea în interiorul suportului.

Deasupra imaginii va fi stratul suprapus.

? // Iniționați un strat suprapus și plasați-l deasupra imaginii var $ overlay = $ ('
') .css (opacitate: options.overlayOpacity, position:' absolut ') .width ($ image.width ()) .height ($ image.height ()) .insertAfter ($ image);

Acest strat are aceeași dimensiune ca și imaginea, dar, de asemenea, a primit o poziționare absolută. Obținem valoarea pentru opacitate din options.overlayOpacity și lăsați-l să aplice jQuery. Acest element are, de asemenea, un ID, astfel încât să putem schimba proprietățile sale prin intermediul foii de stil a plug-in-ului. În partea de jos, numim .insertAfter () metoda de a plasa stratul suprapus chiar după imagine.

Următorul strat este stratul de declanșare; îl vom plasa după stratul suprapus, la fel ca în cazul celor precedente.

? // Inițializați un strat de declanșare și plasați-l deasupra stratului suprapus var $ trigger = $ ('
') .css (backgroundColor:' # 000000 ', opacitate: 0, poziție:' absolut ') .width ($ image.width ()) .height ($ image.height ;

Culoarea de fundal nu contează, dar trebuie să fie diferită de cea transparentă (care este implicită). Acest strat este invizibil de la utilizator, dar se va ocupa de anumite evenimente.

Vom plasa stratul contur deasupra stratului de declansare.

? // Inițializați un strat de contur și plasați-l deasupra stratului de declanșare var $ outline = $ ('
') .css (opacitate: options.outlineOpacitate, poziție:' absolut ') .insertAfter ($ trigger);

Și, în final, ultimul strat.

? // Inițializați un strat de selecție și plasați-l deasupra stratului contur var $ selection = $ ('
') .css (background:' url ('+ $ image.attr (' src ') +') nu-repeta ', pozitie:' absolut ') .insertAfter ($ outline);

.attr () metoda returnează valoarea unui atribut specificat. Am folosit-o pentru a obține imaginea src și a setat-o ​​ca fundal pentru stratul de selecție.

Poziția absolută în poziționarea relativă

S-ar putea să știți deja acest lucru, dar un element cu o poziție relativă vă oferă controlul pentru a poziționa absolut elementele din interiorul acestuia. Acesta este motivul pentru care stratul suport are o poziție relativă și toți copiii săi o poziție absolută.

O explicație excelentă a acestui truc este acoperită în acest articol.


Pasul 6. Actualizarea interfeței

În primul rând, vom inițializa unele variabile.

? // Initializeaza variabilele globale var selectionExists, selectionOffset = [0, 0], selectionOrigin = [0, 0]; 

selectionExists ne va informa dacă există o selecție. selectionOffset va conține decalajul față de originea imaginii și selectionOrigin va indica originea selecției. Lucrurile vor fi mult mai clare după câțiva pași.

Următoarele condiții sunt necesare dacă selecția există atunci când plug-in-ul este încărcat.

? // Verificați dacă dimensiunea selecției este mai mare decât minimul acceptat // și setați existența selecției în mod corespunzător dacă (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; altceva selectionExists = false; 

Apoi vom apela updateInterface () pentru prima dată pentru a inițializa interfața.

? // Apelați funcția 'updateInterface' pentru prima dată pentru a // inițializa interfața plug-in updateInterface (); 

Vom scrie corpul acestei funcții în scurt timp. Acum, să ne ocupăm de primul nostru eveniment.

? dacă (options.allowSelect) // Legați un handler de evenimente la evenimentul "mousedown" al stratului de declanșare $ trigger.mousedown (setSelection); 

Noi sunam .mousedown () dacă options.allowSelect este Adevărat. Aceasta va lega un handler de evenimente la mousedown eveniment al stratului de declanșare. Deci, dacă un utilizator face clic pe imagine, setSelection () va fi invocată.

? // Obțineți compensarea curentă a unei funcții element getElementOffset (obiect) var offset = $ (obiect) .offset (); retur [offset.left, offset.top]; ; // Obțineți poziția curentă a mouse-ului față de funcția de poziție a imaginii getMousePosition (eveniment) var imageOffset = getElementOffset ($ image); var x = eveniment.pageX - imageOffset [0], y = eveniment.pageY - imageOffset [1]; x = (x < 0) ? 0 : (x > $ image.width ())? $ imagine.width (): x; y = (y < 0) ? 0 : (y > $ image.height ())? $ image.height (): y; retur [x, y]; ; 

Prima funcție, getElementOffset (), returnează coordonatele stânga și de sus ale obiectului specificat în raport cu documentul. Am recuperat această valoare sunând la .offset () metodă. A doua funcție, getMousePosition (), returnează poziția actuală a mouse-ului, dar relativ la poziția imaginii. Deci, vom lucra cu valori care sunt doar între 0 și lățimea / înălțimea imaginii de pe axa x / y, respectiv.

Să scriem o funcție pentru actualizarea straturilor noastre.

? // Actualizați actualizarea funcției strat suprapusOverlayLayer () $ overlay.css (display: selectionExists? 'Block': 'none'); ; 

Această funcție verifică valoarea selectionExists variabilă și determină dacă stratul suprapus ar trebui să fie afișat sau nu.

? // Actualizați funcția stratului de declanșare updateTriggerLayer () $ trigger.css (cursor: options.allowSelect? 'Crosshair': 'implicit'); ; 

updateTriggerLayer () funcția schimbă cursorul la crosshair sau Mod implicit, depinzând de options.allowSelect valoare.

Apoi, vom scrie updateSelection () funcţie. Acesta va actualiza nu numai stratul de selecție, ci și stratul conturului.

? // Actualizați funcția de selecție updateSelection () // Actualizați stratul contur $ outline.css (cursor: 'default', afișare: selectionExists? 'Block': 'none', left: options.selectionPosition [0] : options.selectionPosition [1]) .width (opțiuni.selecțieWidth) .height (opțiuni.selecțieHeight); // Actualizați stratul de selecție $ selection.css (backgroundPosition: (- options.selectionPosition [0] - 1) + 'px' + (- options.selectionPosition [1] - 1) + 'px', cursor: opțiuni. (0) + 1, top: options.selectionPosition [1] + 1) .width ((Opțiuni) .secție (lățime - 2> 0)? (opțiuni.selecțieLățime - 2): 0) .Hifa ((opțiuni.selecțieHeight - 2> 0)? ; 

În primul rând, această funcție stabilește proprietățile stratului contur: cursorul, afișajul, mărimea și poziția sa. Urmează stratul de selecție; noua valoare a poziției de fundal va face ca imaginile să se suprapună fără probleme.

Acum, avem nevoie de o funcție de actualizare a cursorului când este necesar. De exemplu, atunci când facem o selecție, dorim ca cursorul să rămână a crosshair indiferent de stratul pe care l-am terminat.

? // Actualizați funcția tip cursor updateCursor (cursorType) $ trigger.css (cursor: cursorType); $ outline.css (cursor: cursorType); $ selection.css (cursor: cursorType); ; 

Da, este la fel de simplu cum arată. Doar modificați tipul cursorului la cel specificat!

Și acum, ultima funcție a acestui pas; avem nevoie de actualizarea interfeței plug-in-ului în diferite situații - la selectarea, la redimensionare, la eliberarea selecției și chiar și atunci când plug-in-ul inițializează.

? // Actualizați funcția de interfață a plug-in-ului updateInterface (expeditor) comutare (expeditor) case 'setSelection': updateOverlayLayer (); updateSelection (); pauză; caz "resizeSelection": updateSelecție (); updateCursor ( 'reticul'); pauză; implicit: updateTriggerLayer (); updateOverlayLayer (); updateSelection (); ; 

După cum puteți vedea, updateInterface () funcția filtrează câteva cazuri și solicită funcțiile necesare pe care tocmai le-am scris.


Pasul 7. Setarea selecției

Până acum, am avut grijă de opțiunile de personalizare și de interfață, dar nimic nu se referea la modul în care utilizatorul interacționează cu plug-in-ul. Să scriem o funcție care stabilește o nouă selecție atunci când se face clic pe imagine.

? // Setați o nouă funcție de selecție setSelection (eveniment) // Preveniți acțiunea implicită a evenimentului event.preventDefault (); // Preveniți ca evenimentul să nu fie notificat event.stopPropagation (); // Legați un handler de evenimente la evenimentele 'mousemove' și 'mouseup' $ (document) .mousemove (resizeSelection) .mouseup (releaseSelection); // Notifică că există o selecție selectionExists = true; // Resetați opțiunile pentru dimensiunea selecției.selecțieWidth = 0; options.selectionHeight = 0; // Obțineți selecția de origine a selecțieiOrigin = getMousePosition (eveniment); // și setați opțiunile sale de poziție. Selecție Poziție [0] = selectOrigin [0]; options.selectionPosition [1] = selectionOrigin [1]; // Actualizați numai elementele necesare ale interfeței plug-in // prin specificarea expeditorului actualizării apelului curentInterface ('setSelection'); ; 

În primul rând, setSelection funcția solicită două metode: event.preventDefault () și event.stopPropagation (). Acest lucru împiedică acțiunea implicită și eventuala manipulare a părinților să fie notificată despre eveniment. .mousemove () metoda leagă un manipulator eveniment la mousemove eveniment. Aceasta va apela resizeSelection () funcționează de fiecare dată când utilizatorul mișcă indicatorul mouse-ului. Pentru a anunța o nouă selecție, selectionExists variabilă este făcută Adevărat iar dimensiunea selecției este setată la 0. Apoi, obținem originea selecției apelând funcția noastră scrisă anterior, getMousePosition (), și să treacă valoarea sa la options.selectionPosition. În cele din urmă, numim updateInterface () funcția de a actualiza interfața plug-in-ului în funcție de modificările efectuate.


Pasul 8. Redimensionarea selecției

În etapa anterioară am scris o funcție pentru setarea unei noi selecții. Să scriem acum o funcție pentru redimensionarea acelei selecții.

? // Redimensionați funcția curentă de selecție redimensionareSelecție (eveniment) // Preveniți acțiunea implicită a evenimentului event.preventDefault (); // Preveniți ca evenimentul să nu fie notificat event.stopPropagation (); var mousePosition = getMousePosition (eveniment); // Obțineți opțiunile pentru mărimea selecției.selecțieWidth = mousePosition [0] - selectionOrigin [0]; options.selectionHeight = mousePosition [1] - selecțieOrigin [1]; dacă (opțiuni.selecțieWidth < 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'); ; 

Pentru a redimensiona selecția, trebuie să preluăm poziția curentă a mouse-ului. Deoarece valoarea returnată este relativă la dimensiunea imaginii, trebuie să avem grijă numai de valorile negative. Nu va depăși limitele imaginii. După cum știți, nu putem avea o valoare negativă pentru lăţime sau înălţime proprietățile unui element. Pentru a rezolva asta, sunăm Math.abs () pentru a obține valoarea absolută și apoi repoziționăm selecția.


Pasul 9. Eliberarea selecției

Și acum funcția finală:

? // Eliberați funcția de selecție curentăSelecție (eveniment) // Preveniți acțiunea implicită a evenimentului event.preventDefault (); // Preveniți ca evenimentul să nu fie notificat event.stopPropagation (); // Deblocați dispozitivul de tratare a evenimentelor la evenimentul "mousemove" $ (document) .unbind ('mousemove'); // Deblocați dispozitivul de tratare a evenimentelor la evenimentul "mouseup" $ (document) .unbind ('mouseup'); // Actualizați selecția de origine a selecțieiOrigin [0] = options.selectionPosition [0]; selectionOrigin [1] = options.selectionPosition [1]; // Verificați dacă dimensiunea selecției este mai mare decât minimul acceptat // și setați existența selecției în mod corespunzător dacă (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minSelect [1]) selectionExists = true; altceva selectionExists = false; // Actualizați numai elementele necesare ale interfeței plug-in // prin specificarea expeditorului actualizării apelului curentInterface ('releaseSelection'); ; 

Când se selectează selecția, releaseSelection () funcția elimină agenții de preluare a evenimentelor atașați anterior în setSelection () funcția prin apelarea .desface() metodă. Apoi, actualizează originea selecției și testează dimensiunea minimă acceptată pentru ca selecția să existe.

Acum suntem aproape gata. Închideți acest fișier și pregătiți-l pentru următorul pas.


Pasul 10. Styling Plug-In

Deschide /resources/js/imageCrop/jquery.imagecrop.css și adăugați următoarele linii.

 div # imagine-cultură-suprapunere background-color: #ffffff; overflow: ascuns;  div # imagine-cultură-schiță background: #ffffff url ('outline.gif'); overflow: ascuns; 

Nu este nimic complicat aici; am adăugat un anumit stil pentru straturile suprapuse și conturul.


Pasul 11. Testarea rezultatului final

Pentru a testa pluginul nostru, trebuie să îl atașăm la o imagine. Să facem acest lucru și să îl editați index.html pagină.

Deschide scenariu etichetă?

  

? și scrieți următorul cod JavaScript.

 $ (document) .ready (funcția () $ ('img # example'). imageCrop (overlayOpacity: 0.25); 

Am atașat pluginul nostru la elementul de imagine cu exemplu id și setați câteva opțiuni personalizate. Am folosit .gata() pentru a determina când DOM este încărcat complet.

Si asta e! Salvați fișierul și deschideți browserul pentru al testa.


Ce urmeaza

Acum avem un jQuery plug-in de bază care ne permite să selectăm o zonă a imaginii. În următorul tutorial, vom adăuga mai multe opțiuni de personalizare, vom construi un panou de previzualizare, vom scrie câteva script-uri de la server pentru a decupa imaginea? și mult mai mult. Sper că v-ați bucurat de timpul petrecut împreună și ați descoperit că acest tutorial este util. Vă mulțumim pentru lectură!