prihlasenyprihlasit | registrovat

Ako vytvoriť jQuery plugin na orezávanie obrázka od základu - časť II

Webové aplikácie potrebujú jednoducho použiteľné riešenie pre upload a manipuláciu bohatého obsahu. Tento proces môže spôsobovať problémy niektorým používateľom, ktorí majú minimálne znalosti s úpravou fotografií. Orezávanie je jednou z najpoužívanejších metód pre manipuláciu s fotografiami a tento tutoriál sa bude vzťahovať na celý vývojový proces jQuery pluginu na orezávanie obrázka.

Rýchla rekapitulácia

V tutoriáli Ako vytvoriť jQuery plugin na orezávanie obrázka od základu - časť I sme zistili:
  • ako rozšíriť jQuery
  • ako urobiť plugin flexibilnejším použitím voliteľných možností
  • ako vytvoriť základ aplikácie na orezávanie obrázka

Dnes sa pozrieme na veci viac do hĺbky a rozšírime náš plugin: definujeme si ďalšie možnosti, pridáme callback, pridáme výberu možnosť presúvania a zmeny veľkosti, vytvoríme náhľad a informácie o veľkosti a napíšeme si nejaký kód po strane servera na orezanie obrázka.

Krok 1: Pridanie ďalších možností

Otvorte svoj jquery.imagecrop.js súbor umiestnený v jquery.imagecrop.js a pridajte nasledujúci kód:

var defaultOptions = {
    allowMove : true,
    allowResize : true,
    allowSelect : true,
    aspectRatio : 0,
    displayPreview : false,
    displaySizeHint : false,
    minSelect : [0, 0],
    minSize : [0, 0],
    maxSize : [0, 0],
    outlineOpacity : 0.5,
    overlayOpacity : 0.5,
    previewBoundary : 90,
    previewFadeOnBlur : 1,
    previewFadeOnFocus : 0.35,
    selectionPosition : [0, 0],
    selectionWidth : 0,
    selectionHeight : 0,

    // Plugin udalost handlery
    onChange : function() {},
    onSelect : function() {}
};

Pridali sme ďalšie možnosti a dve callbacky, onChange a onSelect. Tieto dve môžu byť celkom užitočné v získavaní stavu pluginu.

Možnosti

Tu je rýchly prehľad možností, ktoré sme pridali:

  • aspectRatio – Určuje pomer strán výberu (predvolená hodnota je 0)
  • displayPreview – Určuje, či je náhľad zobrazený alebo nie (predvolená hodnota je false)
  • displaySizeHint – Určuje, či informácie o veľkosti sú zobrazené alebo nie (predvolená hodnota je false)
  • minSize – Určuje minimálnu veľkosť výberu (predvolená hodnota je [0, 0])
  • maxSize – Určuje maximálnu veľkosť výberu (predvolená hodnota je [0, 0])
  • previewBoundary – Určuje veľkosť náhľadu (predvolená hodnota je 90)
  • previewFadeOnBlur – Určuje priehľadnosť náhľadu mimo kurzor (predvolená hodnota je 1)
  • previewFadeOnFocus – Určuje priehľadnosť pod kurzorom (predvolená hodnota je 0.35)
  • onCahnge – Vráti stav pluginu, keď je zmenený výber
  • onSelect – Vráti stav pluginu, keď je vytvorený výber

Krok 2: Pridanie viacerých vrstiev

V tomto kroku budeme pridávať ďalšie vrstvy. Začneme s informáciami o veľkosti.

...

// Inicializuje background vrstvu informacii o velkosti a umiestni ju nad selection vrstvu
var $sizeHintBackground = $('
') .css({ opacity : 0.35, position : 'absolute' }) .insertAfter($selection); // Inicializuje foreground vrstvu informacii velkosti a umiestni ju nad background vrstvu var $sizeHintForeground = $('') .css({ position : 'absolute' }) .insertAfter($sizeHintBackground);

Pridáme dve oddelené vrstvy, pretože nechceme, aby popredie ovplyvňovalo priehľadnosť pozadia.

Teraz pridáme ďalších deväť vrstiev: rozširovacie úchyty

...

// Inicializuje severozapadny rozsirovaci uchyt a umiestni ho nad selection vrstvu
var $nwResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje severny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $nResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje severovychodny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $neResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje zapadny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $wResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje vychodny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $eResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje juhozapadny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $swResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje juzny rozsirovaci uchyt a umiestni ho selection vrstvu var $sResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Inicializuje juhovychodny rozsirovaci uchyt a umiestni ho nad selection vrstvu var $seResizeHandler = $('
') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection);

Inicializujeme veľkosť úchytov pre každý roh a stred strany.

A konečne, náhľad.

...

// Inicializuje nahlad a umiestni ho po outline vrstve
var $previewHolder = $('
') .css({ opacity : options.previewFadeOnBlur, overflow : 'hidden', position : 'absolute' }) .insertAfter($outline); // Inicializuje nahlad obrazka a pridá ho do nahladu var $preview = $('Crop preview') .css({ position : 'absolute' }) .attr('src', $image.attr('src')) .appendTo($previewHolder);

Inicializujeme dve vrstvy:

  • úchyt, ktorý funguje ako maska a
  • náhľad, ktorý má rovnaký src ako pôvodný obrázok

Použili sme .appendTo() metódu pre vloženie náhľadu obrázka na koniec úchytu.

Krok 3: Zlepšenie rozhrania

Po prvé, pridáme dve nové globálne premenné.

...

// Inicializuje globalne premenne
var resizeHorizontally = true,
    resizeVertically = true,
    selectionExists,
    selectionOffset = [0, 0],
    selectionOrigin = [0, 0];

Tieto premenné budeme potrebovať neskôr, keď budeme aktualizovať resizeSelection() funkciu.

V prvej časti sme sa starali len o allowSelect možnosť. Poďme sa postarať tiež o allowMove a allowResize.

...

if (options.allowMove)
    // Zviaze handler udalost na 'mousedown' udalost selection vrstvy
    $selection.mousedown(pickSelection);

if (options.allowResize)
    // Zviaze handler udalost na 'mousedown' udalost rozsirovacich uchytov
    $('div.image-crop-resize-handler').mousedown(pickResizeHandler);

Pripojili sme mousedown udalosť na výber a všetky rozširovacie úchyty.

Teraz musíme napísať trošku viac kódu pre aktualizovanie predtým novo-pridanej vrstvy.

...

// Aktualizuje informacie o velkosti
function updateSizeHint(action) {
    switch (action) {
        case 'fade-out' :
            // Zmiznutie informacii o velkosti
            $sizeHintBackground.fadeOut('slow');
            $sizeHintForeground.fadeOut('slow');

            break;
        default :
            var display = (selectionExists && options.displaySize) ? 'block' : 'none';

            // Aktualizuje foreground vrstvu
            $sizeHintForeground.css({
                    cursor : 'default',
                    display : display,
                    left : options.selectionPosition[0] + 4,
                    top : options.selectionPosition[1] + 4
                })
                .html(options.selectionWidth + 'x' + options.selectionHeight);

            // Aktualizuje background vrstvu
            $sizeHintBackground.css({
                    cursor : 'default',
                    display : display,
                    left : options.selectionPosition[0] + 1,
                    top : options.selectionPosition[1] + 1
                })
                .width($sizeHintForeground.width() + 6)
                .height($sizeHintForeground.height() + 6);
    }
};

Funkcia updateSizeHint() obsluhuje dva prípady v závislosti od zadaného parametra.

  • Pokiaľ nie je zadaný, predvolené správanie je zobraziť a aktualizovať informácie o veľkosti (ak existuje výber).
  • Druhá možnosť je miznutie informácie. To bude použité, keď užívateľ ukončí zväčšovanie.

V predchádzajúcom kroku sme veľkosť úchytov len inicializovali. Teraz ich umiestnime na správne pozície.

...

// Aktualizuje rozsirovacie úchyty
function updateResizeHandlers(action) {
    switch (action) {
        case 'hide-all' :
            $('.image-crop-resize-handler').each(function() {
                $(this).css({
                        display : 'none'
                    });
            });

            break;
        default :
            var display = (selectionExists && options.allowResize) ? 'block' : 'none';

            $nwResizeHandler.css({
                    cursor : 'nw-resize',
                    display : display,
                    left : options.selectionPosition[0] - Math.round($nwResizeHandler.width() / 2),
                    top : options.selectionPosition[1] - Math.round($nwResizeHandler.height() / 2)
                });

            $nResizeHandler.css({
                    cursor : 'n-resize',
                    display : display,
                    left : options.selectionPosition[0] + Math.round(options.selectionWidth / 2 - $neResizeHandler.width() / 2) - 1,
                    top : options.selectionPosition[1] - Math.round($neResizeHandler.height() / 2)
                });

            $neResizeHandler.css({
                    cursor : 'ne-resize',
                    display : display,
                    left : options.selectionPosition[0] + options.selectionWidth - Math.round($neResizeHandler.width() / 2) - 1,
                    top : options.selectionPosition[1] - Math.round($neResizeHandler.height() / 2)
                });

            $wResizeHandler.css({
                    cursor : 'w-resize',
                    display : display,
                    left : options.selectionPosition[0] - Math.round($neResizeHandler.width() / 2),
                    top : options.selectionPosition[1] + Math.round(options.selectionHeight / 2 - $neResizeHandler.height() / 2) - 1
                });

            $eResizeHandler.css({
                    cursor : 'e-resize',
                    display : display,
                    left : options.selectionPosition[0] + options.selectionWidth - Math.round($neResizeHandler.width() / 2) - 1,
                    top : options.selectionPosition[1] + Math.round(options.selectionHeight / 2 - $neResizeHandler.height() / 2) - 1
                });

            $swResizeHandler.css({
                    cursor : 'sw-resize',
                    display : display,
                    left : options.selectionPosition[0] - Math.round($swResizeHandler.width() / 2),
                    top : options.selectionPosition[1] + options.selectionHeight - Math.round($swResizeHandler.height() / 2) - 1
                });

            $sResizeHandler.css({
                    cursor : 's-resize',
                    display : display,
                    left : options.selectionPosition[0] + Math.round(options.selectionWidth / 2 - $seResizeHandler.width() / 2) - 1,
                    top : options.selectionPosition[1] + options.selectionHeight - Math.round($seResizeHandler.height() / 2) - 1
                });

            $seResizeHandler.css({
                    cursor : 'se-resize',
                    display : display,
                    left : options.selectionPosition[0] + options.selectionWidth - Math.round($seResizeHandler.width() / 2) - 1,
                    top : options.selectionPosition[1] + options.selectionHeight - Math.round($seResizeHandler.height() / 2) - 1
                });
    }
};

Podobne ako posledná funkcia, updateResizeHandlers() testuje dva prípady: hide-all a default. V prvom prípade voláme .each() metódu pre prechádzanie zodpovedajúcimi elementami.

Poďme vytvoriť updatePreview() funkciu.

...

// Aktualizuje nahlad
function updatePreview(action) {
    switch (action) {
        case 'focus' :
            // Zobrazi nahlad vrstvu
            $previewHolder.stop()
                .animate({
                    opacity : options.previewFadeOnFocus
                });

            break;
        case 'blur' :
            // Zmizne nahlad vrstva
            $previewHolder.stop()
                .animate({
                    opacity : options.previewFadeOnBlur
                });

            break;
        case 'hide' :
            // Skryje nahlad vrstvu
            $previewHolder.css({
                display : 'none'
            });

            break;
        default :
            var display = (selectionExists && options.displayPreview) ? 'block' : 'none';

            // Aktualizuje nahlad vrstvu
            $previewHolder.css({
                    display : display,
                    left : options.selectionPosition[0],
                    top : options.selectionPosition[1] + options.selectionHeight + 10
                });

            // Update the preview size
            if (options.selectionWidth > options.selectionHeight) {
                if (options.selectionWidth && options.selectionHeight) {
                    // Aktualizuje velkost nahladu
                    $preview.width(Math.round($image.width() * options.previewBoundary / options.selectionWidth));
                    $preview.height(Math.round($image.height() * $preview.width() / $image.width()));

                    // Aktualizuje velkost vrstvy nahladu
                    $previewHolder.width(options.previewBoundary)
                    .height(Math.round(options.selectionHeight * $preview.height() / $image.height()));
                }
            } else {
                if (options.selectionWidth && options.selectionHeight) {
                    // Aktualizuje velkost obrazkoveho nahladu
                    $preview.height(Math.round($image.height() * options.previewBoundary / options.selectionHeight));
                    $preview.width(Math.round($image.width() * $preview.height() / $image.height()));

                    // Aktualizuje velkost vrstvy nahladu
                    $previewHolder.width(Math.round(options.selectionWidth * $preview.width() / $image.width()))
                        .height(options.previewBoundary);
                }
            }

            // Aktualizuje poziciu obrazkoveho nahladu
            $preview.css({
                left : - Math.round(options.selectionPosition[0] * $preview.width() / $image.width()),
                top : - Math.round(options.selectionPosition[1] * $preview.height() / $image.height())
            });
    }
};

Kód pre prvé tri prípady by mal byť jasný. Zavoláme .animate() metódu pre vykonanie vlastnej animácie CSS vlastností. Ďalej rozhodneme display hodnotu a nastavíme pozíciu náhľadu.

Musíme tiež aktualizovať updateCursor() funkciu.

...

// Aktualizuje typ kurzora
function updateCursor(cursorType) {
    $trigger.css({
            cursor : cursorType
        });

    $outline.css({
            cursor : cursorType
        });

    $selection.css({
            cursor : cursorType
        });

    $sizeHintBackground.css({
            cursor : cursorType
        });

    $sizeHintForeground.css({
            cursor : cursorType
        });
};

A teraz posledná funkcia tohto kroku.

...

//  Aktualizuje rozhranie pluginu
function updateInterface(sender) {
    switch (sender) {
        case 'setSelection' :
            updateOverlayLayer();
            updateSelection();
            updateResizeHandlers('hide-all');
            updatePreview('hide');

            break;
        case 'pickSelection' :
            updateResizeHandlers('hide-all');

            break;
        case 'pickResizeHandler' :
            updateSizeHint();
            updateResizeHandlers('hide-all');

            break;
        case 'resizeSelection' :
            updateSelection();
            updateSizeHint();
            updateResizeHandlers('hide-all');
            updatePreview();
            updateCursor('crosshair');

            break;
        case 'moveSelection' :
            updateSelection();
            updateResizeHandlers('hide-all');
            updatePreview();
            updateCursor('move');

            break;
        case 'releaseSelection' :
            updateTriggerLayer();
            updateOverlayLayer();
            updateSelection();
            updateSizeHint('fade-out');
            updateResizeHandlers();
            updatePreview();

            break;
        default :
            updateTriggerLayer();
            updateOverlayLayer();
            updateSelection();
            updateResizeHandlers();
            updatePreview();
    }
};

Krok 4: Vylepšenie setSelection()

Pridáme tu len jednu vec: podpora náhľadu

...

// Nastavi novy vyber
function setSelection(event) {
    // Zabrani predvolenej akcii spustit jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    // Zviaze handler udalosti na 'mousemove' udalost
    $(document).mousemove(resizeSelection);

    // Zviaze handler udalosti na 'mouseup ' udalost
    $(document).mouseup(releaseSelection);

    // Ak je zobrazenie nahladu povolene
    if (options.displayPreview) {
        // Zviaze handler udalosti na 'mouseenter' udalost nahladu
        $previewHolder.mouseenter(function() {
            updatePreview('focus');
         });

         // Zviaze handler udalosti na 'mouseleave' udalost nahladu
         $previewHolder.mouseleave(function() {
             updatePreview('blur');
         });
    }

    // Zaznamena, ze existuje vyber
    selectionExists = true;

    // Resetne velkost vyberu
    options.selectionWidth = 0;
    options.selectionHeight = 0;

    // Ziska povodny vyber
    selectionOrigin = getMousePosition(event);

    // A nastavi jeho poziciu
    options.selectionPosition[0] = selectionOrigin[0];
    options.selectionPosition[1] = selectionOrigin[1];

    // Update only the needed elements of the plug-in interface
    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania 
};

Testovali sme displayPreview možnosť a použili .mouseenter() a .mouseleave() funkcie pre pripojenie handler udalosti, pre náhľad.

Krok 5: Uchytenie výberu

Aby bol výber posúvateľným, potrebujeme zistiť, kedy užívateľ presunie a pustí tlačidlo myši.

...

// Oznaci aktualny vyber
function pickSelection(event) {
    // Zabrani predvolenej akcii spustit jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    // Zviaze handler udalosti z 'mousemove' udalosti
    $(document).mousemove(moveSelection);

    // Zviaze handler udalosti z 'mouseup' udalosti
    $(document).mouseup(releaseSelection);

    var mousePosition = getMousePosition(event);

    // Ziska odsadenie vyberu relativne k pozicii mysi
    selectionOffset[0] = mousePosition[0] - options.selectionPosition[0];
    selectionOffset[1] = mousePosition[1] - options.selectionPosition[1];

    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania
    updateInterface('pickSelection');
};

Tiež získame odsadenie výberu vzhľadom k pozícii myši. To budeme potrebovať neskôr, v moveSelection() funkcii.

Krok 6: Uchytenie rozširovacích úchytov

Užívateľ bude môcť meniť veľkosť výberu chytením a potiahnutím jedného z úchytov. A to možno vykonať dvoma spôsobmi: v oboch osiach - ak sa užívateľ rozhodne ťahať úchyt z rohu – alebo jednej osi – ak užívateľ zvoli ťahať úchyt zo stredu strany.

...

// Oznaci jeden z rozisoracich uchytov
function pickResizeHandler(event) {
// Zabrani predvolenej akcii spustit jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    switch (event.target.id) {
        case 'image-crop-nw-resize-handler' :
            selectionOrigin[0] += options.selectionWidth;
            selectionOrigin[1] += options.selectionHeight;
            options.selectionPosition[0] = selectionOrigin[0] - options.selectionWidth;
            options.selectionPosition[1] = selectionOrigin[1] - options.selectionHeight;

            break;
        case 'image-crop-n-resize-handler' :
            selectionOrigin[1] += options.selectionHeight;
            options.selectionPosition[1] = selectionOrigin[1] - options.selectionHeight;

            resizeHorizontally = false;

            break;
        case 'image-crop-ne-resize-handler' :
            selectionOrigin[1] += options.selectionHeight;
            options.selectionPosition[1] = selectionOrigin[1] - options.selectionHeight;

            break;
        case 'image-crop-w-resize-handler' :
            selectionOrigin[0] += options.selectionWidth;
            options.selectionPosition[0] = selectionOrigin[0] - options.selectionWidth;

            resizeVertically = false;

            break;
        case 'image-crop-e-resize-handler' :
            resizeVertically = false;

            break;
        case 'image-crop-sw-resize-handler' :
            selectionOrigin[0] += options.selectionWidth;
            options.selectionPosition[0] = selectionOrigin[0] - options.selectionWidth;

            break;
        case 'image-crop-s-resize-handler' :
            resizeHorizontally = false;

            break;
    }

    // Zviaze handler udalosti z 'mousemove' udalosti
    $(document).mousemove(resizeSelection);

    // Zviaze handler udalosti z 'mouseup' udalosti
    $(document).mouseup(releaseSelection);

    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania
    updateInterface('pickResizeHandler');
};

Napísali sme možnosť pre každý úchyt, pretože každý z nich potrebuje špecifické nastavenia.

Krok 7: Vylepšenie resizeSelection()

Narozdiel od prvej verzie resizeSelection() funkcie, bude možné testovať minimálnu/maximálnu veľkosť a zámok pre pomer strán výberu.

...

// Zmeni velkost aktualneho vyberu
function resizeSelection(event) {
    // Zabrani predvolenej akcii spustit jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    var mousePosition = getMousePosition(event);

    // Ziska velkost vyberu
    var height = mousePosition[1] - selectionOrigin[1],
        width = mousePosition[0] - selectionOrigin[0];

    // Ak je velkost vyberu mensia ako minimalna velkost, ponecha minimalnu velkost
    if (Math.abs(width) < options.minSize[0])
        width = (width >= 0) ? options.minSize[0] : - options.minSize[0];

    if (Math.abs(height) < options.minSize[1])
        height = (height >= 0) ? options.minSize[1] : - options.minSize[1];

    // Testuje, ci velkost vyberu presahuje hranice obrazka
    if (selectionOrigin[0] + width < 0 || selectionOrigin[0] + width > $image.width())
        width = - width;

    if (selectionOrigin[1] + height < 0 || selectionOrigin[1] + height > $image.height())
        height = - height;

    if (options.maxSize[0] > options.minSize[0] &&
        options.maxSize[1] > options.minSize[1]) {
        // Testuje, či velkost vyberu je vacsia ako maximalna velkost
        if (Math.abs(width) > options.maxSize[0])
            width = (width >= 0) ? options.maxSize[0] : - options.maxSize[0];

        if (Math.abs(height) > options.maxSize[1])
            height = (height >= 0) ? options.maxSize[1] : - options.maxSize[1];
    }

    // Nastavi velkost vyberu
    if (resizeHorizontally)
        options.selectionWidth = width;

    if (resizeVertically)
        options.selectionHeight = height;

    // Ak je specifikovany pomer strán
    if (options.aspectRatio) {
        // Vypočíta novú sirku a vysku
        if ((width > 0 && height > 0) || (width < 0 && height < 0))
            if (resizeHorizontally)
                height = Math.round(width / options.aspectRatio);
            else
                width = Math.round(height * options.aspectRatio);
        else
            if (resizeHorizontally)
                height = - Math.round(width / options.aspectRatio);
            else
                width = - Math.round(height * options.aspectRatio);

        // Testuje, či nová veľkosť presahuje hranice obrazka
        if (selectionOrigin[0] + width > $image.width()) {
            width = $image.width() - selectionOrigin[0];
            height = (height > 0) ? Math.round(width / options.aspectRatio) : - Math.round(width / options.aspectRatio);
        }

        if (selectionOrigin[1] + height < 0) {
            height = - selectionOrigin[1];
            width = (width > 0) ? - Math.round(height * options.aspectRatio) : Math.round(height * options.aspectRatio);
        }

        if (selectionOrigin[1] + height > $image.height()) {
            height = $image.height() - selectionOrigin[1];
            width = (width > 0) ? Math.round(height * options.aspectRatio) : - Math.round(height * options.aspectRatio);
        }

        // Nastavi velkost vyberu
        options.selectionWidth = width;
        options.selectionHeight = height;
    }

    if (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];

   // Spusti 'onChange' udalost pri zmene vyberu
    options.onChange(getCropData());

    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania
    updateInterface('resizeSelection');
};

Okrem toho sme použili onChange() callback na konci funkcie. getCropData() funkcia vracia aktuálny stav pluginu.

Krok 8: Presunutie výberu

Teraz budeme písať moveSelection() funkciu.

...

// Presunie aktualny výber
function moveSelection(event) {
    // Zabrani predvolenej akcii jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    var mousePosition = getMousePosition(event);

    // Nastavi poziciu vyberu na osi X relativne k hraniciam obrazka
    if (mousePosition[0] - selectionOffset[0] > 0)
        if (mousePosition[0] - selectionOffset[0] + options.selectionWidth < $image.width())
            options.selectionPosition[0] = mousePosition[0] - selectionOffset[0];
        else
            options.selectionPosition[0] = $image.width() - options.selectionWidth;
    else
        options.selectionPosition[0] = 0;

    // Nastavi poziciu vyberu na osi Y relativne k hraniciam obrazka
    if (mousePosition[1] - selectionOffset[1] > 0)
        if (mousePosition[1] - selectionOffset[1] + options.selectionHeight < $image.height())
            options.selectionPosition[1] = mousePosition[1] - selectionOffset[1];
        else
            options.selectionPosition[1] = $image.height() - options.selectionHeight;
        else
            options.selectionPosition[1] = 0;

    // Spusti 'onChange' udalost pri zmene vyberu
    options.onChange(getCropData());

    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania
    updateInterface('moveSelection');
};

Rovnako ako predtým, vyvoláme onChange() callback na konci funkcie.

Krok 9: Vylepšenie releaseSelection()

Musíme tiež upraviť releaseSelection() funkciu.

...

// Uvolni aktualny vyber
function releaseSelection(event) {
    // Zabrani predvolenej akcii spustit jej udalost
    event.preventDefault();

    // Zabrani zaznamenaniu udalosti
    event.stopPropagation();

    // Odviaze handler udalosti z 'mousemove' udalosti 
    $(document).unbind('mousemove');

    // Odviaze handler udalosti z 'mouseup' udalosti 
    $(document).unbind('mouseup');

    // Aktualizuje povodny vyber
    selectionOrigin[0] = options.selectionPosition[0];
    selectionOrigin[1] = options.selectionPosition[1];

    // Resetne obmedzenie velkosti
    resizeHorizontally = true;
    resizeVertically = true;

    // Skontroluje, ci velkost vyberu je vacsia ako minimum a nastavi vyber podla existencie
    if (options.selectionWidth > options.minSelect[0] &&
        options.selectionHeight > options.minSelect[1])
        selectionExists = true;
    else
        selectionExists = false;

    // Spusti 'onSelect' udalost pri vytvoreni vyberu
    options.onSelect(getCropData());

    // Ak neexistuje vyber
    if (!selectionExists) {
        // Odviaze handler udalosti z 'mouseenter' udalosti nahladu
        $previewHolder.unbind('mouseenter');

        // Odviaze handler udalosti z 'mouseleave' udalosti nahladu
        $previewHolder.unbind('mouseleave');
    }

    // Aktualizuje iba potrebne elementy rozhrania pluginu specifikovanim odosielatela aktualneho volania
    updateInterface('releaseSelection');
};

Resetli sme veľkostné obmedzenia a pridali podporu pre náhľad. Tiež sme použili onSelect() callback rovnakým spôsobom, ako sme to urobili predtým s onChange() funkciou.

Krok 10: Získanie aktuálneho stavu

Teraz sme takmer pripravení. Poďme napísať getCropData() funkciu.

...

// Vrati objekt obsahujuci informacie o stave pluginu
function getCropData() {
    return {
        selectionX : options.selectionPosition[0],
        selectionY : options.selectionPosition[1],
        selectionWidth : options.selectionWidth,
        selectionHeight : options.selectionHeight,

        selectionExists : function() {
            return selectionExists;
        }
    };
};

Práve sme napísali poslednú funkciu tohto súboru. Uložte ho a pripravte sa na ďalší krok.

Krok 11: Zmenšovanie (minifying) kódu

V tomto kroku zmenšíme kód pluginu pre redukovanie veľkosti a zrýchlime načítavanie. Toto riešenie spočíva v odstránení zbytočných znakov, ako sú komentáre, medzery, nové riadky a tabulátory. Dva populárne nástroje pre zmenšovanie JavaScript kódu sú YUI Compressor (ktorý tiež zmenšuje CSS) a JSMin. Použijeme prvý. Mimochodom, program je open-source, takže sa môžete pozrieť na kód pre presné pochopenie, ako funguje.

Použitie YUI Compressora

YUI Compressor je napísaný v Jave, takže nezáleží na tom, aký operačný systém používate. Jedinou podmienkou je Java >= 1.4. Stiahnite si YUI Compressor a rozbaľte ho do /resources/js/imageCrop/ priečinka. Otvorte príkazový riadok a zmeňte aktuálny pracovný adresár na túto cestu.

Ak ho používate prvýkrát, mali by ste začať tým, že vykonáte nasledujúci riadok v príkazovom riadku a prečítate si návod na použitie.

$ java -jar yuicompressor-xyzjar

Poďme zmenšiť náš kód.

$ java -jar yuicompressor-xyzjar jquery.imagecrop.js -o jquery.imagecrop.js –preserve-semi

Nezabudnite prepísať xyz na YUI Compressor verziu, ktorú používate.

Krok 12: Štýlovanie nových elementov

Otvorte /resources/js/imageCrop/jquery.imagecrop.css a pridajte doň nasledujúce riadky:

...

div#image-crop-size-hint-background {
    background-color : #000000;
}

span#image-crop-size-hint-foreground {
    color : #ffffff;
    font-family : 'Verdana', 'Geneva', sans-serif;
    font-size : 12px;
    text-shadow : 0 -1px 0 #000000;
}

div#image-crop-preview-holder {
    -moz-box-shadow : 0 0 5px #000000;
    -webkit-box-shadow : 0 0 5px #000000;
    border : 3px #ef2929 solid;
    box-shadow : 0 0 5px #000000;
}

img#image-crop-preview {
    border : none;
}

div.image-crop-resize-handler {
    background-color : #000000;
    border : 1px #ffffff solid;
    height : 7px;
    overflow : hidden;
    width : 7px;
}

Pridali sme trošku štýlu informáciám o veľkosti, náhľadom a rozširovacím úchytom.

Krok 13: Testovanie konečného výsledku

Najprv poďme načítať zmenšený (minified) plugin.

Aby bolo možné plugin testovať, musíme nejako získať veľkosť a pozíciu výberu. To je dôvod, prečo použijeme onSelect callback; ktorý vráti objekt s aktuálnym stavom pluginu.

$(document).ready(function() {
    $('img#example').imageCrop({
        displayPreview : true,
        displaySize : true,
        overlayOpacity : 0.25,

        onSelect : updateForm
    });
});

var selectionExists;

// Aktualizuje formularove inputy
function updateForm(crop) {
    $('input#x').val(crop.selectionX);
    $('input#y').val(crop.selectionY);
    $('input#width').val(crop.selectionWidth);
    $('input#height').val(crop.selectionHeight);

    selectionExists = crop.selectionExists();
};

// Validuje formularove data
function validateForm() {
    if (selectionExists)
        return true;

    alert('Please make a selection first!');

    return false;
};

updateForm() funkcia nastaví input hodnoty a uchová ich, ak existuje výber. Ďalej validateForm() funkcia testuje, či existuje výber, a ak je to potrebné, zobrazí pop-up alert.

Poďme pridať formulár.

...



Pridali sme niekoľko skrytých input polí a submit tlačidlo.

PHP

V tomto príklade použijeme PHP s GD knižnicou, ale môžete použiť akýkoľvek iný server-side skriptovací jazyk, ktorý podporuje grafickú knižnicu.

Vytvorte prázdny súbor, pomenujte ho crop.php a spustite svoj editor.

 $dst_h)
        {
            $dst_h = $dst_h * $boundary / $dst_w;
            $dst_w = $boundary;
        }
        else
        {
            $dst_w = $dst_w * $boundary / $dst_h;
            $dst_h = $boundary;
        }

        // Inicializuje kvalitu vystupneho obrazka
        $quality = 80;

        // Nastavi zdrojovu cestu obrazka
        $src_path = 'resources/images/example.jpg';

        // Vytvori novy obrazok zo zdrojovej cesty obrazka
        $src_image = imagecreatefromjpeg($src_path);

        // Vytvori vystupny obrazok ako true color obrazok specifikovanej velkosti
        $dst_image = imagecreatetruecolor($dst_w, $dst_h);

        // Skopiruje a zmeni velkost zdrojoveho obrazka s prevzorkovanim vystupneho obrazka
        imagecopyresampled($dst_image, $src_image, 0, 0, $_POST['x'],
                           $_POST['y'], $dst_w, $dst_h, $_POST['width'],
                           $_POST['height']);

        // Odstrani zdrojovy obrazok
        imagedestroy($src_image);

        // Posle surovu HTTP hlavicku
        header('Content-type: image/jpeg');

        // Vysle obrazok do prehliadaca
        imagejpeg($dst_image, null, $quality);

        // Odstrani vystupny obrazok
        imagedestroy($dst_image);

        // Ukonci aktualny skript
        exit();
    }
?>

Použili sme imagecreatefromjpeg() metódu na vytvorenie nového obrázka zo zdrojovej adresy a imagecreatetruecolor() pre vytvorenie výstupu ako true color obrázka. Ďalej zavoláme imagecopyresampled() pre skopírovanie a zmenu veľkosti časti obrázka s prevzorkovaním. Súčasný typ dokumentu nie je to, čo potrebujeme, takže zavoláme header() funkciu pre zmenu typu na image/jpeg. Obrázky, ktoré viac nepotrebujeme, sú zničené pomocou imagedestroy() funkcie. Pomocou exit() zastavíme vykonávanie aktuálneho skriptu.

To je všetko

Teraz máme plne prispôsobiteľný jQuery plugin na orezávanie obrázka, ktorý umožňuje užívateľovi vytvárať, posúvať, meniť veľkosť výberu a zobrazovať informácie o veľkosti a náhľade. A áno, vyzerá to rovnako aj v Internet Explorer 6! Týmto je dvojdielny tutoriál na konci, vďaka za prečítanie!

http://net.tutsplus.com/tutorials/javascript-ajax/how-to-create-a-jquery-image-cropping-plug-in-from-scratch-part-ii/

celkom 0

Komentáre

Zatiaľ žiadne komentáre

© 2009 Shaddow admin hosting od VIPHosting