Cara Membuat Plugin JQuery Image Cropping dari Scratch - Bagian II
Indonesian (Bahasa Indonesia) translation by Suci Rohini (you can also view the original English article)



Aplikasi web perlu menyediakan solusi yang mudah digunakan untuk mengunggah dan memanipulasi konten yang kaya. Proses ini dapat menimbulkan kesulitan bagi beberapa pengguna yang memiliki keterampilan mengedit foto minimal. Memotong adalah salah satu teknik manipulasi foto yang paling sering digunakan, dan tutorial langkah demi langkah ini akan mencakup seluruh proses pengembangan plug-in pemangkasan gambar untuk pustaka JavaScript jQuery.
Rekap Cepat
Dalam tutorial sebelumnya, kita mengulas:
- bagaimana cara memperpanjang jQuery
- cara membuat plug-in lebih fleksibel dengan menggunakan opsi khusus
- cara membuat aplikasi pemangkasan gambar dasar
Hari ini, kita akan mengambil langkah lebih lanjut dan menyelesaikan plug-in: kita akan menentukan lebih banyak opsi khusus, menambahkan panggilan balik, membuat pilihan dapat diseret dan diubah ukurannya, membuat panel pratinjau dan petunjuk ukuran dan menulis beberapa kode sisi server untuk potong gambar.
Langkah 1: Menambahkan Opsi Lainnya
Buka file jquery.imagecrop.js
Anda yang berlokasi di /resources/js/imageCrop/
dan tambahkan kode berikut:
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, // Plug-in's event handlers onChange : function() {}, onSelect : function() {} };
Kita telah menambahkan lebih banyak opsi dan dua panggilan balik, onChange
dan onSelect
. Keduanya bisa sangat berguna dalam mengambil status plug-in.
Opsi
Berikut ini ikhtisar cepat opsi yang ditambahkan:
- aspectRatio - Menentukan aspek rasio pemilihan (nilai default adalah
0
). - displayPreview - Menentukan apakah panel pratinjau terlihat atau tidak (nilai default
false
) - displaySizeHint - Menentukan apakah petunjuk ukuran terlihat atau tidak (nilai default
false
) - minSize - Menentukan ukuran minimum pemilihan (nilai default adalah
[0, 0]
) - maxSize - Menentukan ukuran maksimum seleksi (nilai default adalah
[0, 0]
) - previewBoundary - Menentukan ukuran panel pratinjau (nilai default adalah
90
) - previewFadeOnBlur - Menentukan opacity dari panel pratinjau pada blur (nilai default adalah
1
) - previewFadeOnFocus - Menentukan opacity dari panel pratinjau pada fokus (nilai default adalah
0.35
) - onChange - Mengembalikan status plug-in ketika pilihan diubah
- onSelect - Mengembalikan status plug-in saat pemilihan dilakukan
Langkah 2: Tambahkan Lebih Banyak Layer
Pada langkah ini, kita akan menambahkan lebih banyak layer. Mari kita mulai dengan petunjuk ukuran.
... // Initialize a background layer of size hint and place it above the // selection layer var $sizeHintBackground = $('<div id="image-crop-size-hint-background" />') .css({ opacity : 0.35, position : 'absolute' }) .insertAfter($selection); // Initialize a foreground layer of size hint and place it above the // background layer var $sizeHintForeground = $('<span id="image-crop-size-hint-foreground" />') .css({ position : 'absolute' }) .insertAfter($sizeHintBackground);
Kita telah menambahkan dua layer terpisah karena kita tidak ingin foreground dipengaruhi oleh opacity background.
Sekarang kita akan menambahkan sembilan layer lagi: penangan ukuran.
... // Initialize a north/west resize handler and place it above the // selection layer var $nwResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-nw-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize a north resize handler and place it above the selection // layer var $nResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-n-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize a north/east resize handler and place it above the // selection layer var $neResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-ne-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize an west resize handler and place it above the selection // layer var $wResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-w-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize an east resize handler and place it above the selection // layer var $eResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-e-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize a south/west resize handler and place it above the // selection layer var $swResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-sw-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize a south resize handler and place it above the selection // layer var $sResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-s-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection); // Initialize a south/east resize handler and place it above the // selection layer var $seResizeHandler = $('<div class="image-crop-resize-handler" id="image-crop-se-resize-handler" />') .css({ opacity : 0.5, position : 'absolute' }) .insertAfter($selection);
Kita telah menginisialisasi penangan ukuran untuk setiap sudut dan sisi tengah.
Dan akhirnya, panel pratinjau.
... // Initialize a preview holder and place it after the outline layer var $previewHolder = $('<div id="image-crop-preview-holder" />') .css({ opacity : options.previewFadeOnBlur, overflow : 'hidden', position : 'absolute' }) .insertAfter($outline); // Initialize a preview image and append it to the preview holder var $preview = $('<img alt="Crop preview" id="image-crop-preview" />') .css({ position : 'absolute' }) .attr('src', $image.attr('src')) .appendTo($previewHolder);
Kita telah menginisialisasi dua layer:
- pemegang, yang berfungsi sebagai topeng dan
- gambar pratinjau, yang memiliki
src
yang sama dengan gambar aslinya.

Kita telah menggunakan metode .appendTo(
) untuk menyisipkan gambar pratinjau di akhir dudukan.
Langkah 3: Meningkatkan Interface
Pertama, kita akan menambahkan dua variabel global baru.
... // Initialize global variables var resizeHorizontally = true, resizeVertically = true, selectionExists, selectionOffset = [0, 0], selectionOrigin = [0, 0];
Kita akan membutuhkan variabel-variabel ini nanti, ketika memperbarui fungsi resizeSelection()
.
Pada bagian pertama, kita hanya menangani opsi allowSelect
. Mari kita menangani allowMove
dan allowResize
juga.
... if (options.allowMove) // Bind an event handler to the 'mousedown' event of the selection layer $selection.mousedown(pickSelection); if (options.allowResize) // Bind an event handler to the 'mousedown' event of the resize handlers $('div.image-crop-resize-handler').mousedown(pickResizeHandler);
Kita telah melampirkan acara mousedown
ke seleksi dan semua penangan ulang ukuran.
Sekarang kita perlu menulis lebih banyak kode untuk memperbarui layer baru yang telah ditambahkan sebelumnya.
... // Update the size hint function updateSizeHint(action) { switch (action) { case 'fade-out' : // Fade out the size hint $sizeHintBackground.fadeOut('slow'); $sizeHintForeground.fadeOut('slow'); break; default : var display = (selectionExists && options.displaySize) ? 'block' : 'none'; // Update the foreground layer $sizeHintForeground.css({ cursor : 'default', display : display, left : options.selectionPosition[0] + 4, top : options.selectionPosition[1] + 4 }) .html(options.selectionWidth + 'x' + options.selectionHeight); // Update the background layer $sizeHintBackground.css({ cursor : 'default', display : display, left : options.selectionPosition[0] + 1, top : options.selectionPosition[1] + 1 }) .width($sizeHintForeground.width() + 6) .height($sizeHintForeground.height() + 6); } };
Fungsi updateSizeHint()
menangani dua kasus tergantung pada parameter yang ditentukan.
- Jika tidak ada yang ditentukan, perilaku default adalah untuk menampilkan dan memperbarui petunjuk ukuran (jika ada pilihan).
- Perilaku kedua adalah memudar petunjuk. Ini akan digunakan ketika pengguna selesai dengan mengubah ukuran seleksi.
Pada langkah sebelumnya, kita hanya menginisialisasi penangan ukuran. Sekarang kita akan menempatkan mereka di posisi yang tepat.
... // Update the resize handlers 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 }); } };
Mirip dengan fungsi terakhir, updateResizeHandlers()
menguji dua kasus: hide-all
dan default
. Dalam kasus pertama, kita memanggil metode .each()
untuk beralih pada elemen yang cocok.
Mari kita buat fungsi updatePreview()
.
... // Update the preview function updatePreview(action) { switch (action) { case 'focus' : // Fade in the preview holder layer $previewHolder.stop() .animate({ opacity : options.previewFadeOnFocus }); break; case 'blur' : // Fade out the preview holder layer $previewHolder.stop() .animate({ opacity : options.previewFadeOnBlur }); break; case 'hide' : // Hide the preview holder layer $previewHolder.css({ display : 'none' }); break; default : var display = (selectionExists && options.displayPreview) ? 'block' : 'none'; // Update the preview holder layer $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) { // Update the preview image size $preview.width(Math.round($image.width() * options.previewBoundary / options.selectionWidth)); $preview.height(Math.round($image.height() * $preview.width() / $image.width())); // Update the preview holder layer size $previewHolder.width(options.previewBoundary) .height(Math.round(options.selectionHeight * $preview.height() / $image.height())); } } else { if (options.selectionWidth && options.selectionHeight) { // Update the preview image size $preview.height(Math.round($image.height() * options.previewBoundary / options.selectionHeight)); $preview.width(Math.round($image.width() * $preview.height() / $image.height())); // Update the preview holder layer size $previewHolder.width(Math.round(options.selectionWidth * $preview.width() / $image.width())) .height(options.previewBoundary); } } // Update the preview image position $preview.css({ left : - Math.round(options.selectionPosition[0] * $preview.width() / $image.width()), top : - Math.round(options.selectionPosition[1] * $preview.height() / $image.height()) }); } };
Kode untuk tiga kasus pertama harus jelas. Kita memanggil metode .animate()
untuk melakukan animasi khusus dari set off properti CSS. Selanjutnya, kita memutuskan nilai display
dan mengatur posisi pemegang pratinjau. Kemudian, kita skala gambar pratinjau agar sesuai dengan opsi PreviewBoundary
dan menghitung posisi baru.
Kita juga perlu memperbarui fungsi updateCursor()
.
... // Update the cursor type function updateCursor(cursorType) { $trigger.css({ cursor : cursorType }); $outline.css({ cursor : cursorType }); $selection.css({ cursor : cursorType }); $sizeHintBackground.css({ cursor : cursorType }); $sizeHintForeground.css({ cursor : cursorType }); };
Dan sekarang, fungsi terakhir dari langkah ini.
... // Update the plug-in interface 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(); } };
Langkah 4: Meningkatkan setSelection()
Kita akan menambahkan satu hal di sini: dukungan untuk panel pratinjau.
... // Set a new selection function setSelection(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified event.stopPropagation(); // Bind an event handler to the 'mousemove' event $(document).mousemove(resizeSelection); // Bind an event handler to the 'mouseup' event $(document).mouseup(releaseSelection); // If display preview option is enabled if (options.displayPreview) { // Bind an event handler to the 'mouseenter' event of the preview // holder $previewHolder.mouseenter(function() { updatePreview('focus'); }); // Bind an event handler to the 'mouseleave' event of the preview // holder $previewHolder.mouseleave(function() { updatePreview('blur'); }); } // Notify that a selection exists selectionExists = true; // Reset the selection size options.selectionWidth = 0; options.selectionHeight = 0; // Get the selection origin selectionOrigin = getMousePosition(event); // And set its position options.selectionPosition[0] = selectionOrigin[0]; options.selectionPosition[1] = selectionOrigin[1]; // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('setSelection'); };
Kita telah menguji opsi displayPreview
dan menggunakan fungsi .mouseenter()
dan .mouseleave()
untuk melampirkan penangan acara ke pemegang pratinjau.
Langkah 5: Memilih Pilihan
Untuk membuat seleksi dapat diseret, kita perlu menyimpulkan ketika pengguna bergerak dan melepaskan tombol mouse.
... // Pick the current selection function pickSelection(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified event.stopPropagation(); // Bind an event handler to the 'mousemove' event $(document).mousemove(moveSelection); // Bind an event handler to the 'mouseup' event $(document).mouseup(releaseSelection); var mousePosition = getMousePosition(event); // Get the selection offset relative to the mouse position selectionOffset[0] = mousePosition[0] - options.selectionPosition[0]; selectionOffset[1] = mousePosition[1] - options.selectionPosition[1]; // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('pickSelection'); };
Selain itu, kita memiliki pemilihan offset relatif terhadap posisi mouse. Kita akan membutuhkannya nanti, di fungsi moveSelection()
.
Langkah 6: Memilih Penangan Ubah Ukuran
Pengguna akan dapat mengubah ukuran seleksi dengan memilih dan menyeret salah satu penangan ukuran. Dan ini dapat dilakukan dengan dua cara: pada kedua sumbu - jika pengguna memilih untuk menarik pawang dari sudut - atau pada satu sumbu - jika pengguna memilih untuk menarik pawang dari tengah sisi.
... // Pick one of the resize handlers function pickResizeHandler(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified 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; } // Bind an event handler to the 'mousemove' event $(document).mousemove(resizeSelection); // Bind an event handler to the 'mouseup' event $(document).mouseup(releaseSelection); // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('pickResizeHandler'); };
Kita telah menulis sebuah case untuk setiap handler ukuran, karena masing-masing membutuhkan pengaturan spesifik.
Langkah 7: Meningkatkan resizeSelection()
Berbeda dari versi pertama, fungsi resizeSelection()
akan dapat menguji ukuran minimum/maksimum dan mengunci rasio aspek pemilihan.
... // Resize the current selection function resizeSelection(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified event.stopPropagation(); var mousePosition = getMousePosition(event); // Get the selection size var height = mousePosition[1] - selectionOrigin[1], width = mousePosition[0] - selectionOrigin[0]; // If the selection size is smaller than the minimum size set it // accordingly 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]; // Test if the selection size exceeds the image bounds 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]) { // Test if the selection size is bigger than the maximum size 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]; } // Set the selection size if (resizeHorizontally) options.selectionWidth = width; if (resizeVertically) options.selectionHeight = height; // If any aspect ratio is specified if (options.aspectRatio) { // Calculate the new width and height 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); // Test if the new size exceeds the image bounds 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); } // Set the selection size 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]; // Trigger the 'onChange' event when the selection is changed options.onChange(getCropData()); // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('resizeSelection'); };
Selain itu, kita telah memanggil panggilan balik onChange()
di akhir fungsi. Fungsi getCropData()
mengembalikan status plug-in saat ini. Kita akan menulis tubuhnya beberapa langkah kemudian.
Langkah 8: Memindahkan Pilihan
Sekarang kita akan menulis fungsi moveSelection()
.
... // Move the current selection function moveSelection(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified event.stopPropagation(); var mousePosition = getMousePosition(event); // Set the selection position on the x-axis relative to the bounds // of the image 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; // Set the selection position on the y-axis relative to the bounds // of the image 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; // Trigger the 'onChange' event when the selection is changed options.onChange(getCropData()); // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('moveSelection'); };
Seperti sebelumnya, kita telah memanggil Callback onChange()
di akhir fungsi.
Langkah 9: Meningkatkan releaseSelection()
Kita juga perlu mengedit fungsi releaseSelection()
.
... // Release the current selection function releaseSelection(event) { // Prevent the default action of the event event.preventDefault(); // Prevent the event from being notified event.stopPropagation(); // Unbind the event handler to the 'mousemove' event $(document).unbind('mousemove'); // Unbind the event handler to the 'mouseup' event $(document).unbind('mouseup'); // Update the selection origin selectionOrigin[0] = options.selectionPosition[0]; selectionOrigin[1] = options.selectionPosition[1]; // Reset the resize constraints resizeHorizontally = true; resizeVertically = true; // Verify if the selection size is bigger than the minimum accepted // and set the selection existence accordingly if (options.selectionWidth > options.minSelect[0] && options.selectionHeight > options.minSelect[1]) selectionExists = true; else selectionExists = false; // Trigger the 'onSelect' event when the selection is made options.onSelect(getCropData()); // If the selection doesn't exist if (!selectionExists) { // Unbind the event handler to the 'mouseenter' event of the // preview $previewHolder.unbind('mouseenter'); // Unbind the event handler to the 'mouseleave' event of the // preview $previewHolder.unbind('mouseleave'); } // Update only the needed elements of the plug-in interface // by specifying the sender of the current call updateInterface('releaseSelection'); };
Kita telah mengatur ulang batasan ukuran dan menambahkan dukungan untuk panel pratinjau. Selain itu, kita telah memanggil callback onSelect()
dengan cara yang sama seperti yang dilakukan sebelumnya dengan fungsi onChange()
.
Langkah 10: Mendapatkan Keadaan Saat Ini
Sekarang, kita hampir siap. Mari kita tulis fungsi getCropData()
.
... // Return an object containing information about the plug-in state function getCropData() { return { selectionX : options.selectionPosition[0], selectionY : options.selectionPosition[1], selectionWidth : options.selectionWidth, selectionHeight : options.selectionHeight, selectionExists : function() { return selectionExists; } }; };
Kita baru saja menulis fungsi terakhir dari file ini. Simpan dan siapkan untuk langkah selanjutnya.
Langkah 11: Meminimalkan Kode
"Meminimalkan kode mengurangi ukurannya dan meningkatkan waktu pemuatan."
Pada langkah ini, kita akan memperkecil kode plug-in kami untuk mengurangi ukurannya dan meningkatkan waktu pemuatan. Praktek ini terdiri dari menghilangkan karakter yang tidak perlu seperti komentar, spasi, baris baru dan tab. Dua tool populer untuk memperkecil kode JavaScript adalah YUI Compressor (yang juga dapat memperkecil CSS) dan JSMin. Kita akan menggunakan yang pertama. Juga, ini adalah open-source, sehingga Anda dapat melihat kode untuk memahami cara kerjanya.
Menggunakan Kompresor YUI
Kompresor YUI ditulis dalam Java, jadi tidak masalah sistem operasi yang digunakan. Satu-satunya persyaratan adalah Java >= 1.4. Download Kompresor YUI dan ekstrak di folder /resources/js/imageCrop/
. Buka baris perintah dan ubah direktori kerja saat ini ke jalur yang sama.
Jika Anda menggunakannya untuk pertama kali, Anda harus mulai dengan menjalankan baris berikut di baris perintah dan membaca instruksi penggunaan.
$ java -jar yuicompressor-x.y.z.jar
Sekarang mari kita minify kodenya.
$ java -jar yuicompressor-x.y.z.jar jquery.imagecrop.js -o jquery.imagecrop.js --preserve-semi
Jangan lupa mengganti x.y.z
dengan versi Kompresor YUI yang digunakan. Dan itu dia; tunggu hingga selesai dan kemudian tutup jendela baris perintah.
Langkah 12: Menata Elemen Baru
Buka /resources/js/imageCrop/jquery.imagecrop.css
dan tambahkan baris berikut ini:
... 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; }
Kita telah menambahkan beberapa gaya untuk petunjuk ukuran, panel pratinjau, dan mengubah ukuran penangan.
Langkah 13: Menguji Hasil Akhir
Pertama, mari muat plug-in yang diperkecil.
<script src="resources/js/imageCrop/jquery.imagecrop.min.js" type="text/javascript"></script>
Untuk dapat menguji plug-in, kita perlu entah bagaimana mendapatkan ukuran dan posisi pemilihan. Itu sebabnya kita akan menggunakan onSelect
callback; mengembalikan objek dengan status plug-in saat ini.
$(document).ready(function() { $('img#example').imageCrop({ displayPreview : true, displaySize : true, overlayOpacity : 0.25, onSelect : updateForm }); }); var selectionExists; // Update form inputs 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(); }; // Validate form data function validateForm() { if (selectionExists) return true; alert('Please make a selection first!'); return false; };
Fungsi updateForm()
mengatur nilai input dan mempertahankannya jika ada pilihan. Selanjutnya, fungsi validateForm()
menguji jika pilihan ada dan menampilkan pop-up peringatan jika diperlukan.
Mari kita tambahkan formulir.
... <br /><br /> <form action="crop.php" method="post" onsubmit="return validateForm();"> <input id="x" name="x" type="hidden" /> <input id="y" name="y" type="hidden" /> <input id="width" name="width" type="hidden" /> <input id="height" name="height" type="hidden" /> <input type="submit" value="Crop Image" /> </form>
Kita telah menambahkan beberapa input tersembunyi dan tombol kirim.
PHP
Dalam contoh ini, kita akan menggunakan PHP dengan pustaka gd tetapi Anda dapat menggunakan bahasa skrip sisi server lain yang mendukung pustaka grafis.
Buat file kosong, beri nama crop.php
dan jalankan editor Anda.
<?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { // Initialize the size of the output image $boundary = 150; $dst_w = $_POST['width']; $dst_h = $_POST['height']; if ($dst_w > $dst_h) { $dst_h = $dst_h * $boundary / $dst_w; $dst_w = $boundary; } else { $dst_w = $dst_w * $boundary / $dst_h; $dst_h = $boundary; } // Initialize the quality of the output image $quality = 80; // Set the source image path $src_path = 'resources/images/example.jpg'; // Create a new image from the source image path $src_image = imagecreatefromjpeg($src_path); // Create the output image as a true color image at the specified size $dst_image = imagecreatetruecolor($dst_w, $dst_h); // Copy and resize part of the source image with resampling to the // output image imagecopyresampled($dst_image, $src_image, 0, 0, $_POST['x'], $_POST['y'], $dst_w, $dst_h, $_POST['width'], $_POST['height']); // Destroy the source image imagedestroy($src_image); // Send a raw HTTP header header('Content-type: image/jpeg'); // Output the image to browser imagejpeg($dst_image, null, $quality); // Destroy the output image imagedestroy($dst_image); // Terminate the current script exit(); } ?>
Kita telah menggunakan metode imagecreatefromjpeg()
untuk membuat gambar baru dari jalur sumber dan imagecreatetruecolor()
untuk membuat output sebagai gambar warna yang benar. Selanjutnya, kita telah memanggil imagecopyresampled()
untuk menyalin dan mengubah ukuran bagian gambar dengan resampling. Jenis dokumen saat ini bukan yang dibutuhkan, jadi kita memanggil fungsi header()
untuk mengubahnya menjadi image/jpeg
. Gambar yang tidak diperlukan lagi dihancurkan dengan fungsi imagedestroy()
. Dengan exit()
, kita menghentikan eksekusi skrip saat ini.
Itu Saja
Kita sekarang memiliki plug-in pemangkasan gambar jQuery yang sepenuhnya dapat disesuaikan yang memungkinkan pengguna untuk membuat, menyeret dan mengubah ukuran pilihan dan menampilkan petunjuk ukuran dan panel pratinjau. Dan ya, tampilannya sama bahkan di Internet Explorer 6! Sehingga selesai adalah tutorial dua bagian! Terima kasih sudah membaca!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly