Webapplikationer behöver tillhandahålla lättanvända lösningar för att ladda upp och hantera rikt innehåll. Denna process kan skapa problem för vissa användare som har minimal bildredigering. Beskärning är en av de mest använda teknikerna för fotobehandling, och den här stegvisa handledningen täcker hela utvecklingsprocessen för en plugin för bildklippning för jQuery JavaScript-biblioteket.
Först ska vi ställa in vårt projekt arbetsområde för denna handledning. Börja med att skapa en hierarki med kataloger och tomma filer med namnet som exempel på bilden nedan:
Därefter måste du hämta jQuery JavaScript-biblioteket och placera det inuti / resurser / js /
mapp. Bilden som används i denna handledning måste namnges example.jpg
och placeras inuti / resurser / images /
mapp. Du kan använda den här bilden (tack vare gsso-lager), försedd med källfilerna i denna handledning, eller en av dina egna. Och den sista filen är outline.gif
fil som måste placeras inuti / Resurser / js / imageCrop /
mapp.
För att testa vår plugin måste vi bifoga den till en bild. Innan vi börjar arbeta med det, skapar vi en enkel sida som innehåller den bilden.
Öppna upp index.html
filen i din favorit textredigerare och skriv följande kod.
jQuery Image Cropping Plug-In jQuery Image Cropping Plug-In
Det finns inget fint här: helt enkelt HTML-kod. Vi har laddat ett stilark för sidan, jQuery, våra plugin-filer (som för tillfället är tomma) och placerat en bild i dokumentet.
Redigera nu style.css
som visas ovan.
* marginal: 0; kontur: 0; vaddering: 0; kropp bakgrundsfärg: #ededed; färg: # 646464; font-family: "Verdana", "Geneva", sans-serif; fontstorlek: 12px; textskugga: 0 1px 0 #ffffff; h1 font-size: 24px; typsnitt: normal; marginal: 0 0 10px 0; div # wrapper margin: 25px 25px 25px 25px; div.image-decorator -moz-border-radius: 5px 5px 5px 5px; -moz-box-skugga: 0 0 6px # c8c8c8; -webkit-gräns-radie: 5px 5px 5px 5px; -webkit-box-skugga: 0 0 6px # c8c8c8; bakgrundsfärg: #ffffff; gräns: 1px fast # c8c8c8; gränsstråle: 5px 5px 5px 5px; boxskugga: 0 0 6px # c8c8c8; display: inline-block; höjd: 360px; vaddering: 5px 5px 5px 5px; bredd: 480px;
Vi har anpassat sidan på vår sida genom att ändra bakgrundsfärgen och lägga till några grundläggande styling till titeln och bilden.
Låt oss börja med att skapa en grundläggande jQuery-plugin.
"Läs mer om hur du skriver din egen plug-in, via det här inlägget. Det beskriver grunderna, bästa metoderna och vanliga fallgropar att se upp för när du börjar skriva in din plugin."
Öppna /resources/js/imageCrop/jquery.imagecrop.js
och lägg till följande kod.
// Alltid sätta ihop ett plugin i '(funktion ($) // Plug-in går här) (jQuery);' (funktion ($) $ .imageCrop = funktion (objekt, customOptions) ; $ .fn.imageCrop = funktion (customOptions) // Iterera över varje objekt this.each (function () var currentObject = den här bilden = ny bild (); // och bifoga imageCrop när objektet är laddat image.onload = function () $ .imageCrop (currentObject, customOptions);; // Återställ src eftersom inte cachade bilder eldar ladda ibland bild .src = currentObject.src;); // Om inte plugin-modulen returnerar ett inneboende värde har du alltid // funktionen returnera "detta" nyckelordet för att upprätthålla kedjansåterkomst;;) (jQuery);
Vi har just förlängt jQuery genom att lägga till en ny funktionsegenskap till jQuery.fn
objekt. Nu har vi en väldigt grundläggande plug-in som iterates över varje objekt och bifogas imageCrop
när objektet är laddat Observera att de cachade bilderna inte brinner ladda
ibland, så vi återställer src
attribut för att åtgärda problemet.
Med hjälp av anpassningsalternativ gör en plug-in mycket flexibelare för användaren.
$ .imageCrop = function (object, customOptions) // I stället för att kräva en lång mängd argument, skicka // plugin-alternativen i ett objekt som är bokstavligt som kan förlängas över // pluginens standardvärden var defaultOptions = allowMove: true, allowResize: true, allowSelect: true, minVälj: [0, 0], outlineOpacity: 0.5, overlayOpacity: 0.5, selectionPosition: [0, 0], selectionWidth: 0, selectionHeight: 0; // Ange alternativ till standard var options = defaultOptions; // och fusionera dem med de anpassade alternativen setOptions (customOptions); ;
Vi har definierat en matris med standardalternativen och slog sedan samman dem med de anpassade alternativen genom att ringa setOptions
fungera. Låt oss gå vidare och skriva kroppen av den här funktionen.
? // Sammanfoga nuvarande alternativ med anpassade alternativfunktionen setOptions (customOptions) options = $ .extend (options, customOptions); ;
De $ .Extend ()
funktionen sammanfogar innehållet i två eller flera objekt tillsammans i det första objektet.
Följande lista beskriver varje alternativ för plugin-modulen.
Sann
).Sann
).Sann
).[0, 0]
).0,5
).0,5
).[0, 0]
).0
).0
).I det här steget kommer vi att ändra DOM för att bli förberedd för nästa steg: pluginens gränssnitt.
Först ska vi initiera bildlagret.
? // Initiera bildlagret var $ image = $ (objekt);
Starta nu en bildhållare.
? // Initiera en bildhållare var $ innehavare = $ ('') .css (position:' relative '). bredd ($ image.width ()) .höjd ($ image.height ()); // Vikta hållaren runt bilden $ image.wrap ($ hållare) .css (position: 'absolute');
Som du kan se har hållarskiktet samma storlek som bilden och en relativ position. Därefter kallar vi .slå in()
funktion för att placera bilden inuti hållaren.
Ovanför bilden blir överlagret.
? // Initiera ett överlagringslager och placera det ovanför bilden var $ overlay = $ ('') .css (opacity: options.overlayOpacity, position:' absolute ') .width ($ image.width ()) .höjd ($ image.height ()) .insertAfter ($ image);
Detta lager är lika stort som bilden, men har också fått absolut positionering. Vi får värdet för opaciteten från options.overlayOpacity
och låt jQuery tillämpa det. Det här elementet har också ett ID, så vi kan ändra dess egenskaper genom pluginens stylesheet. I botten kallar vi .Insert ()
Metod för att placera överlagret direkt efter bilden.
Nästa skikt är utlösningsskiktet; Vi placerar det efter överlagret, precis som vi gjorde med de tidigare.
? // Initiera ett utlösningsskikt och placera det ovanför överlagringslaget var $ trigger = $ ('') .css (backgroundColor:' # 000000 ', opacitet: 0, position:' absolut ') .bredd ($ image.width ()) .höjd ($ image.height ()) .insertAfter ($ överlagring) ;
Bakgrundsfärgen spelar ingen roll, men det måste vara annorlunda än genomskinligt (vilket är som standard). Detta lager är osynligt från användaren men det hanterar vissa händelser.
Vi placerar skiktet ovanför utlösningsskiktet.
? // Initiera ett kontorslager och placera det ovanför utlösningsskiktet var $ outline = $ ('') .css (opacity: options.outlineOpacity, position:' absolute ') .insertAfter ($ trigger);
Och äntligen det sista laget.
? // Initiera ett urvalslager och placera det ovanför kontorslagret var $ selection = $ ('') .css (bakgrund:' url ('+ $ image.attr (' src ') +') no-repeat ', position:' absolute ') .insertAfter ($ skiss);
De .attr ()
Metoden returnerar värdet för ett specificerat attribut. Vi använde det för att få bild src och ange det som bakgrund för urvalskiktet.
Du kanske redan vet det här, men ett element med en relativ positionering ger dig kontrollen om att helt placera element inuti den. Det är därför innehavsskiktet har en relativ position och alla sina barn är en absolut position.
En utmärkt förklaring till detta trick är omtalt i denna artikel.
Först ska vi initiera några variabler.
? // Initiera globala variabler var selectionExists, selectionOffset = [0, 0], selectionOrigin = [0, 0];
De selectionExists
kommer att informera oss om ett val finns. De selectionOffset
kommer att innehålla förskjutningen i förhållande till bildens ursprung och selectionOrigin
kommer att ange ursprunget för urvalet. Saker kommer att bli mycket tydligare efter några steg.
Följande villkor är nödvändiga om valet existerar när plug-in är laddad.
? // Verifiera om urvalsstorleken är större än det minsta tillåtna // och ställ in valets existens i enlighet därvid om (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minVälj [1]) selectionExists = true; annars selectionExists = false;
Nästa ringer vi på updateInterface ()
funktion för första gången för att initiera gränssnittet.
? // Ring funktionen "updateInterface" för första gången till // initiera plugin-gränssnittsuppdateringenInterface ();
Vi ska skriva in den här funktionen inom kort. Låt oss nu ta hand om vår första händelse.
? om (options.allowSelect) // Bind en händelsehanterare till "mousedown" -händelsen av triggerlagret $ trigger.mousedown (setSelection);
Vi ringer .mousedown ()
om options.allowSelect
är Sann
. Detta binder en händelsehanterare till mousedown
händelse av utlösningsskiktet. Så, om en användare klickar på bilden, så setSelection ()
kommer att åberopas.
? // Hämta nuvarande offset för en elementfunktion getElementOffset (objekt) var offset = $ (objekt). Offset (); returnera [offset.left, offset.top]; ; // Hämta nuvarande musposition i förhållande till bildpositionsfunktionen getMousePosition (händelse) 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; returnera [x, y]; ;
Den första funktionen, getElementOffset ()
, returnerar vänster och toppkoordinater för det angivna objektet i förhållande till dokumentet. Vi har hämtat det här värdet genom att ringa .offset()
metod. Den andra funktionen, getMousePosition ()
, returnerar den aktuella muspositionen, men i förhållande till bildpositionen. Så vi arbetar med värden som endast är mellan 0 och bildbredden / höjden på x / y-axeln.
Låt oss skriva en funktion för att uppdatera våra lager.
? // Uppdatera överlagringsfunktionsuppdateringenOverlayLayer () $ overlay.css (display: selectionExists? Block ':' none '); ;
Denna funktion kontrollerar värdet på selectionExists
variabel och bestämmer om överlagret ska visas eller inte.
? // Uppdatera funktionslagsfunktionsuppdateringenTriggerLayer () $ trigger.css (markör: options.allowSelect? 'Crosshair': 'default'); ;
De updateTriggerLayer ()
funktionen ändrar markören till hårkors
eller standard
, beroende på options.allowSelect
värde.
Därefter ska vi skriva updateSelection ()
fungera. Det kommer inte bara att uppdatera urvalskiktet, utan även skiktet.
? // Uppdatera valfunktionsuppdateringenSelektion () // Uppdatera översiktsskiktet $ outline.css (markör: 'default', display: selectionExists? 'Block': 'none', left: options.selectionPosition [0] : options.selectionPosition [1] .width (options.selectionWidth) .height (options.selectionHeight); // Uppdatera valskiktet $ selection.css (backgroundPosition: (- options.selectionPosition [0] - 1) + 'px' + (- options.selectionPosition [1] - 1) + 'px', markör: alternativ. allowMove? "move": "standard", display: selectionExists? block: "none", left: options.selectionPosition [0] + 1, topp: options.selectionPosition [1] + 1) .width .selectionWidth - 2> 0)? (options.selectionWidth - 2): 0) .höjd ((options.selectionHeight - 2> 0)? (options.selectionHeight - 2): 0); ;
Först ställer denna funktion in skiktets egenskaper: markören, displayen, storleken och dess position. Nästa kommer valet lager; Det nya värdet av bakgrundsläget gör att bilderna överlappar sömlöst.
Nu behöver vi en funktion för att uppdatera markören när det behövs. Till exempel, när vi gör ett urval, vill vi att markören ska förbli a hårkors
oavsett vilket lager vi är över.
? // Uppdatera markörtypsfunktionsuppdateringCursor (cursorType) $ trigger.css (cursor: cursorType); $ outline.css (cursor: cursorType); $ selection.css (cursor: cursorType); ;
Ja, det är så enkelt som det ser ut. Ändra bara markörtypen till den angivna!
Och nu, det sista steget i detta steg; Vi behöver det för att uppdatera pluginens gränssnitt i olika situationer - om du väljer, om du vill ändra storlek på att släppa urvalet, och även när plug-in initierar.
? // Uppdatera pluginens gränssnittsfunktionsuppdateringInterface (avsändare) switch (avsändare) case 'setSelection': updateOverlayLayer (); updateSelection (); ha sönder; fallet 'resizeSelection': updateSelection (); updateCursor ( 'hårkorset'); ha sönder; standard: updateTriggerLayer (); updateOverlayLayer (); updateSelection (); ;
Som du kan se, är updateInterface ()
Funktionen filtrerar vissa fall och ringer upp de funktioner som vi just skrivit.
Hittills har vi tagit hand om anpassningsalternativen och gränssnittet, men ingenting relaterat till hur användaren interagerar med plugin-modulen. Låt oss skriva en funktion som sätter ett nytt val när bilden klickas.
? // Ange en ny markeringsfunktion setSelection (event) // Förhindra standardåtgärden för händelsen event.preventDefault (); // Förhindra att händelsen anmäls event.stopPropagation (); // Bind en händelsehanterare till "mousemove" och "mouseup" händelser $ (dokument) .mousemove (resizeSelection) .mouseup (releaseSelection); // Meddela att ett val existerar selectionExists = true; // Återställ valstorlek options.selectionWidth = 0; options.selectionHeight = 0; // Hämta urvalet urval selectionOrigin = getMousePosition (händelse); // Och ställ dess position options.selectionPosition [0] = selectionOrigin [0]; options.selectionPosition [1] = selectionOrigin [1]; // Uppdatera endast de nödvändiga elementen i plug-in-gränssnittet // genom att ange avsändaren för den aktuella samtaluppdateringenInterface ('setSelection'); ;
Först, det setSelection
funktionen kallar två metoder: event.preventDefault ()
och Event.stopPropagation ()
. Detta förhindrar att standardåtgärden och eventuella förälderhanterare meddelas om händelsen. De .mouse ()
Metod binder en händelsehanterare till mouse
händelse. Detta kommer att ringa till resizeSelection ()
funktionen varje gång användaren flyttar muspekaren. För att meddela att ett nytt val görs, ska selectionExists
variabel är gjord Sann
och urvalsstorleken är satt till 0. Därefter får vi urvalets ursprung genom att ringa vår tidigare skrivna funktion, getMousePosition ()
, och överför dess värde till options.selectionPosition
. Slutligen kallar vi updateInterface ()
funktion för att uppdatera pluginens gränssnitt enligt de ändringar som gjorts.
I det föregående steget skrev vi en funktion för att ställa in ett nytt urval. Låt oss nu skriva en funktion för att ändra storlek på det här valet.
? // Ändra storlek på den aktuella urvalsfunktionen resizeSelection (event) // Förhindra standardåtgärden för händelsen event.preventDefault (); // Förhindra att händelsen anmäls event.stopPropagation (); var mousePosition = getMousePosition (händelse); // Hämta valstorlek options.selectionWidth = mousePosition [0] - selectionOrigin [0]; options.selectionHeight = mousePosition [1] - selectionOrigin [1]; om (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'); ;
För att ändra storlek på valet måste vi hämta den aktuella muspositionen. Eftersom det returnerade värdet är relativt bildstorleken, behöver vi bara ta hand om de negativa värdena. Den kommer aldrig att överskrida bildgränserna. Som ni vet kan vi inte ha ett negativt värde för bredd
eller höjd
egenskaper hos ett element. För att lösa detta, vi ringer Math.abs ()
för att få det absoluta värdet och sedan återplacerar vi urvalet.
Och nu den sista funktionen:
? // Släpp den aktuella urvalsfunktionen releaseSelection (händelse) // Förhindra standardåtgärden för händelsen event.preventDefault (); // Förhindra att händelsen anmäls event.stopPropagation (); // Unbind händelsehanteraren till "mousemove" -händelsen $ (dokument) .unbind ('mousemove'); // Unbind händelsehanteraren till "mouseup" -händelsen $ (dokument) .unbind ('mouseup'); // Uppdatera urvalet urval urvalOrigin [0] = options.selectionPosition [0]; selectionOrigin [1] = options.selectionPosition [1]; // Verifiera om urvalsstorleken är större än det minsta tillåtna // och ställ in valets existens i enlighet därvid om (options.selectionWidth> options.minSelect [0] && options.selectionHeight> options.minVälj [1]) selectionExists = true; annars selectionExists = false; // Uppdatera endast de nödvändiga elementen i plug-in-gränssnittet // genom att ange avsändaren för den aktuella samtaluppdateringenInterface ('releaseSelection'); ;
När valet släpps, kommer releaseSelection ()
funktionen tar bort tidigare bifogade händelsehanterare i setSelection ()
funktion genom att ringa .Unbind ()
metod. Därefter uppdateras det urvalets ursprung och testar den minsta storlek som godkänts för att valet ska existera.
Nu är vi nästan redo. Stäng den här filen och förbered dig för nästa steg.
Öppna /resources/js/imageCrop/jquery.imagecrop.css
stylesheet och lägg till följande rader.
div # image-crop-overlay bakgrundsfärg: #ffffff; överflöde: gömd; div # image-crop-outline bakgrund: #ffffff url ('outline.gif'); överflöde: gömd;
Det finns inget komplicerat här; Vi har lagt till en del styling till överlagrings- och kontorslagren.
För att testa vår plugin måste vi bifoga den till en bild. Låt oss göra det och redigera index.html
sida.
Öppna manus
märka?
? och skriv följande JavaScript-kod.
$ (dokument) .ready (funktion () $ ('img # example'). imageCrop (overlayOpacity: 0.25););
Vi har bifogat vårt plugin till bildelementet med exempel
id och ange några anpassade alternativ. Vi använde .redo()
Metod för att bestämma när DOM är fullt laddad.
Och det är allt! Spara filen och öppna webbläsaren för att testa den.
Nu har vi ett jQuery-plugin för grundläggande bildhantering som gör att vi kan välja ett område på en bild. I nästa handledning lägger vi till fler anpassningsalternativ, bygger en förhandsgranskningspanel, skriv några skript på serverns sida för att beskära bilden? och mycket mera. Jag hoppas att du har haft den tid vi har spenderat tillsammans och funnit denna handledning för att vara användbar. Tack för att du läser!