Cara Membuat Crop Gambar Plus Upload dengan PHP
Maaf baru update lagi sahabat mynotescode di karenakan kami sedang ada banyak kesibukan jadi baru bisa update lagi. Oke langsung saja kali ini kita bakalan ngebahas tentang Cara Membuat Upload Gambar Plus Crop Gambar dan seperti biasa kita bakalan membahasnya secara terperinci dan step by step agar kawan-kawan dapat memahaminya dengan mudah
DEMO
Sebelum membaca tutorialnya, mungkin ada yang mau lihat demonya terlebih dahulu. Klik link berikut untuk melihat demonya : Lihat Demo.
STEP 1 – Persiapan
- Download JQUERY : Klik Disini
- Download Bootstrap : Klik Disini
- Download librari JQuery Cropper : Klik Disini
- Buat sebuah folder baru dengan nama crop_upload, lalu simpan pada folder xampp/htdocs/.
- Buat sebuah folder dengan nama css, lalu simpan pada folder xampp/htdocs/crop_upload/.
- Buat sebuah folder dengan nama js, lalu simpan pada folder xampp/htdocs/crop_upload/
- Esktrak file bootstrap.7z yang telah didownload tadi.
- Copy and paste file bootstrap.min.css dari folder bootstrap/css/ yang telah diekstrak tadi ke folder xampp/htdocs/crop_upload/css/.
- Copy and paste file bootstrap.min.js dari folder bootstrap/js/ yang telah diekstrak tadi ke folder xampp/htdocs/crop_upload/js/
- Copy and paste file jquery.min.js yang telah didownload tadi ke folder xampp/htdocs/crop_upload/js/.
- Esktrak file cropper.zip yang telah didownload tadi.
- Copy and paste folder cropper yang telah diesktrak tadi ke folder xampp/htdocs/crop_upload/js/.
STEP 2 – Proses Crop
Sekarang tulis kode javasctript berikut untuk proses upload dan crop gambarnya. Buat sebuah file dengan nama main.js, lalu simpan pada folder xampp/htdocs/crop_upload/js/. Berikut Script javascriptnya :
(function (factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node / CommonJS factory(require('jquery')); } else { // Browser globals. factory(jQuery); } })(function ($) { 'use strict'; var console = window.console || { log: function () {} }; function CropAvatar($element) { // mengambil element this.$container = $element; // memanggil class avatar-view this.$avatarView = this.$container.find('.avatar-view'); // memanggil tag html img this.$avatar = this.$avatarView.find('img'); // memanggil id avatar-modal this.$avatarModal = this.$container.find('#avatar-modal'); // memanggil class loading this.$loading = this.$container.find('.loading'); // memanggil class avatar-form this.$avatarForm = this.$avatarModal.find('.avatar-form'); // memanggil class avatar-form this.$avatarUpload = this.$avatarForm.find('.avatar-upload'); // memanggil class avatar src this.$avatarSrc = this.$avatarForm.find('.avatar-src'); // memanggil class avatar-data this.$avatarData = this.$avatarForm.find('.avatar-data'); // memanggil class avatar-input this.$avatarInput = this.$avatarForm.find('.avatar-input'); // memanggil class avatar save this.$avatarSave = this.$avatarForm.find('.avatar-save'); // memanggil class avatar btns this.$avatarBtns = this.$avatarForm.find('.avatar-btns'); // memanggil avatar-wrapper this.$avatarWrapper = this.$avatarModal.find('.avatar-wrapper'); // memanggil avatar-preview this.$avatarPreview = this.$avatarModal.find('.avatar-preview'); // memanggil function init untuk menjalankan CropAvatar this.init(); } CropAvatar.prototype = { constructor: CropAvatar, support: { fileList: !!$('<input type="file">').prop('files'), blobURLs: !!window.URL && URL.createObjectURL, formData: !!window.FormData }, // function untuk memulai proses cropavatar init: function () { this.support.datauri = this.support.fileList && this.support.blobURLs; if (!this.support.formData) { this.initIframe(); } this.initTooltip(); this.initModal(); this.addListener(); }, // function menambah list gambar agar dapat di munculkan juga di bagian kotak-kotak kiri di atas addListener: function () { this.$avatarView.on('click', $.proxy(this.click, this)); this.$avatarInput.on('change', $.proxy(this.change, this)); this.$avatarForm.on('submit', $.proxy(this.submit, this)); this.$avatarBtns.on('click', $.proxy(this.rotate, this)); }, // function untuk memunculkan title pada saat kursor di dekatkan di gambar untuk menambah gambar initTooltip: function () { this.$avatarView.tooltip({ placement: 'bottom' }); }, // function untuk menampilkan show modal cropper avatar initModal: function () { this.$avatarModal.modal({ show: false }); }, // function untuk menampilkan gambar preview di dalam canvas initPreview: function () { var url = this.$avatar.attr('src'); this.$avatarPreview.html('<img src="' + url + '">%MCEPASTEBIN%'); }, // fungsi untuk membuat frame agar gambar dapat di tampilkan pada canvas initIframe: function () { var target = 'upload-iframe-' + (new Date()).getTime(); var $iframe = $('<iframe>').attr({ name: target, src: '' }); var _this = this; // Ready ifrmae $iframe.one('load', function () { // respond response $iframe.on('load', function () { var data; try { data = $(this).contents().find('body').text(); } catch (e) { console.log(e.message); } if (data) { try { data = $.parseJSON(data); } catch (e) { console.log(e.message); } _this.submitDone(data); } else { _this.submitFail('Image upload failed!'); } _this.submitEnd(); }); }); this.$iframe = $iframe; this.$avatarForm.attr('target', target).after($iframe.hide()); }, // fungsi untuk memulai pertama kali pada saat di klik gambar awal click: function () { this.$avatarModal.modal('show'); this.initPreview(); }, // fungsi untuk merubah ukuran gambar yang akan di crop change: function () { var files; var file; if (this.support.datauri) { files = this.$avatarInput.prop('files'); if (files.length > 0) { file = files[0]; if (this.isImageFile(file)) { if (this.url) { URL.revokeObjectURL(this.url); // Revoke the old one } this.url = URL.createObjectURL(file); this.startCropper(); } } } else { file = this.$avatarInput.val(); if (this.isImageFile(file)) { this.syncUpload(); } } }, // fungsi untuk mengirimkan gambar yang sudah di crop ke proses penyimpana gambar submit: function () { if (!this.$avatarSrc.val() && !this.$avatarInput.val()) { return false; } if (this.support.formData) { this.ajaxUpload(); return false; } }, // fungsi untuk rotasi gambar tersebut pada canvas rotate: function (e) { var data; if (this.active) { data = $(e.target).data(); if (data.method) { this.$img.cropper(data.method, data.option); } } }, // fungsi untuk meng validasi type gambar yang di upload isImageFile: function (file) { if (file.type) { return /^image\/\w+$/.test(file.type); } else { return /\.(jpg|jpeg|png|gif)$/.test(file); } }, // funsgi untuk menjalankan crop gambar startCropper: function () { var _this = this; if (this.active) { this.$img.cropper('replace', this.url); } else { this.$img = $('<img src="' + this.url + '">'); this.$avatarWrapper.empty().html(this.$img); this.$img.cropper({ aspectRatio: 1, preview: this.$avatarPreview.selector, crop: function (e) { var json = [ '{"x":' + e.x, '"y":' + e.y, '"height":' + e.height, '"width":' + e.width, '"rotate":' + e.rotate + '}' ].join(); _this.$avatarData.val(json); } }); this.active = true; } this.$avatarModal.one('hidden.bs.modal', function () { _this.$avatarPreview.empty(); _this.stopCropper(); }); }, // fungsi untuk memberhentikan proses crop yang sedang berjalan stopCropper: function () { if (this.active) { this.$img.cropper('destroy'); this.$img.remove(); this.active = false; } }, // fungsi untuk meng upload gambar yang tadi sudah di masukan dan di proses ajaxUpload: function () { var url = this.$avatarForm.attr('action'); var data = new FormData(this.$avatarForm[0]); var _this = this; $.ajax(url, { type: 'post', data: data, dataType: 'json', processData: false, contentType: false, beforeSend: function () { _this.submitStart(); }, success: function (data) { _this.submitDone(data); }, error: function (XMLHttpRequest, textStatus, errorThrown) { _this.submitFail(textStatus || errorThrown); }, complete: function () { _this.submitEnd(); } }); }, // fungsi untuk membanding kan gambar yang sebelum di crop dengan sesudah di crop syncUpload: function () { this.$avatarSave.click(); }, // fungsi untuk memulai crop submitStart: function () { this.$loading.fadeIn(); }, // fungsi untuk menyimpan hasil setelah proses simpan gambar telah selesai dan menerima response yang di terima submitDone: function (data) { console.log(data); if ($.isPlainObject(data) && data.state === 200) { if (data.result) { this.url = data.result; if (this.support.datauri || this.uploaded) { this.uploaded = false; this.cropDone(); } else { this.uploaded = true; this.$avatarSrc.val(this.url); this.startCropper(); } this.$avatarInput.val(''); } else if (data.message) { this.alert(data.message); } } else { this.alert('Failed to response'); } }, // fungsi ketika proses mengalami ke gagalan akan mengeluarkan pesan error nya submitFail: function (msg) { this.alert(msg); }, // fungsi untuk mengakhiri proses cropper submitEnd: function () { this.$loading.fadeOut(); }, // fungsi ini akan di panggil ketika proses cropper telah selesai cropDone: function () { this.$avatarForm.get(0).reset(); this.$avatar.attr('src', this.url); this.stopCropper(); this.$avatarModal.modal('hide'); }, // fungsi untuk menampilkan pesan error alert: function (msg) { var $alert = [ '<div class="alert alert-danger avatar-alert alert-dismissable">', '<button type="button" class="close" data-dismiss="alert">×</button>', msg, '</div>' ].join(''); this.$avatarUpload.after($alert); } }; // untuk memulai keseluruhan coding yang sudah kita buat tadi supaya dapat berjalan $(function () { return new CropAvatar($('#crop-avatar')); }); });
STEP 3 – View
Buat tampilan dan IMK(Interaksi Manusia Komputer) nya untuk lebih mudah dan enak di gunakan oleh kawan-kawan semua. Buat sebuah file index.html lalu simpan pada folder xampp/htdocs/crop_upload/. Berikut tampilan yang akan kita buat :
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content="A complete example of Cropper."> <meta name="keywords" content="HTML, CSS, JS, JavaScript, jQuery plugin, image cropping, image crop, image move, image zoom, image rotate, image scale, front-end, frontend, web development"> <meta name="author" content="Fengyuan Chen"> <title>Cropper</title> <link rel="stylesheet" href="css/bootstrap.min.css"> <link rel="stylesheet" href="js/cropper/cropper.min.css"> <link rel="stylesheet" href="css/main.css"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div class="container" id="crop-avatar"> <!-- Current avatar --> <div class="avatar-view" title="Change the avatar"> <img src="images/picture.jpg" alt="Avatar"> </div> <!-- Cropping modal --> <div class="modal fade" id="avatar-modal" aria-hidden="true" aria-labelledby="avatar-modal-label" role="dialog" tabindex="-1"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <form class="avatar-form" action="crop.php" enctype="multipart/form-data" method="post"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title" id="avatar-modal-label">Change Avatar</h4> </div> <div class="modal-body"> <div class="avatar-body"> <!-- Upload image and data --> <div class="avatar-upload"> <input type="hidden" class="avatar-src" name="avatar_src"> <input type="hidden" class="avatar-data" name="avatar_data"> <label for="avatarInput">Local upload</label> <input type="file" class="avatar-input" id="avatarInput" name="avatar_file"> </div> <!-- Crop and preview --> <div class="row"> <div class="col-md-9"> <div class="avatar-wrapper"></div> </div> <div class="col-md-3"> <div class="avatar-preview preview-lg"></div> <div class="avatar-preview preview-md"></div> <div class="avatar-preview preview-sm"></div> </div> </div> <div class="row avatar-btns"> <div class="col-md-9"> <div class="btn-group"> <button type="button" class="btn btn-primary" data-method="rotate" data-option="-90" title="Rotate -90 degrees">Rotate Left</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="-15">-15deg</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="-30">-30deg</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="-45">-45deg</button> </div> <div class="btn-group"> <button type="button" class="btn btn-primary" data-method="rotate" data-option="90" title="Rotate 90 degrees">Rotate Right</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="15">15deg</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="30">30deg</button> <button type="button" class="btn btn-primary" data-method="rotate" data-option="45">45deg</button> </div> </div> <div class="col-md-3"> <button type="submit" class="btn btn-primary btn-block avatar-save">Done</button> </div> </div> </div> </div> <!-- <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> --> </form> </div> </div> </div><!-- /.modal --> <!-- Loading state --> <div class="loading" aria-label="Loading" role="img" tabindex="-1"></div> </div> <script src="js/jquery.min.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/cropper/cropper.min.js"></script> <script src="js/main.js"></script> </body> </html>
STEP 4 – Proses Upload
Setelah kita buat tampilannya sekarang kita buat untuk proses upload gambarnya. Buat sebuah file dengan nama crop.php, lalu simpan pada fodler xampp/htdocs/crop_upload/. Berikut skripnya :
<?php class CropAvatar { private $src; private $data; private $dst; private $type; private $extension; private $msg; function __construct($src, $data, $file) { $this -> setSrc($src); $this -> setData($data); $this -> setFile($file); $this -> crop($this -> src, $this -> dst, $this -> data); } private function setSrc($src) { if (!empty($src)) { $type = exif_imagetype($src); if ($type) { $this -> src = $src; $this -> type = $type; $this -> extension = image_type_to_extension($type); $this -> setDst(); } } } private function setData($data) { if (!empty($data)) { $this -> data = json_decode(stripslashes($data)); } } private function setFile($file) { $errorCode = $file['error']; if ($errorCode === UPLOAD_ERR_OK) { $type = exif_imagetype($file['tmp_name']); if ($type) { $extension = image_type_to_extension($type); $src = 'images/' . date('YmdHis') . '.original' . $extension; if ($type == IMAGETYPE_GIF || $type == IMAGETYPE_JPEG || $type == IMAGETYPE_PNG) { if (file_exists($src)) { unlink($src); } $result = move_uploaded_file($file['tmp_name'], $src); if ($result) { $this -> src = $src; $this -> type = $type; $this -> extension = $extension; $this -> setDst(); } else { $this -> msg = 'Failed to save file'; } } else { $this -> msg = 'Please upload image with the following types: JPG, PNG, GIF'; } } else { $this -> msg = 'Please upload image file'; } } else { $this -> msg = $this -> codeToMessage($errorCode); } } private function setDst() { $this -> dst = 'images/' . date('YmdHis') . '.png'; } private function crop($src, $dst, $data) { if (!empty($src) && !empty($dst) && !empty($data)) { switch ($this -> type) { case IMAGETYPE_GIF: $src_img = imagecreatefromgif($src); break; case IMAGETYPE_JPEG: $src_img = imagecreatefromjpeg($src); break; case IMAGETYPE_PNG: $src_img = imagecreatefrompng($src); break; } if (!$src_img) { $this -> msg = "Failed to read the image file"; return; } $size = getimagesize($src); $size_w = $size[0]; // natural width $size_h = $size[1]; // natural height $src_img_w = $size_w; $src_img_h = $size_h; $degrees = $data -> rotate; // Rotate the source image if (is_numeric($degrees) && $degrees != 0) { // PHP's degrees is opposite to CSS's degrees $new_img = imagerotate( $src_img, -$degrees, imagecolorallocatealpha($src_img, 0, 0, 0, 127) ); imagedestroy($src_img); $src_img = $new_img; $deg = abs($degrees) % 180; $arc = ($deg > 90 ? (180 - $deg) : $deg) * M_PI / 180; $src_img_w = $size_w * cos($arc) + $size_h * sin($arc); $src_img_h = $size_w * sin($arc) + $size_h * cos($arc); // Fix rotated image miss 1px issue when degrees < 0 $src_img_w -= 1; $src_img_h -= 1; } $tmp_img_w = $data -> width; $tmp_img_h = $data -> height; $dst_img_w = 220; $dst_img_h = 220; $src_x = $data -> x; $src_y = $data -> y; if ($src_x <= -$tmp_img_w || $src_x > $src_img_w) { $src_x = $src_w = $dst_x = $dst_w = 0; } else if ($src_x <= 0) { $dst_x = -$src_x; $src_x = 0; $src_w = $dst_w = min($src_img_w, $tmp_img_w + $src_x); } else if ($src_x <= $src_img_w) { $dst_x = 0; $src_w = $dst_w = min($tmp_img_w, $src_img_w - $src_x); } if ($src_w <= 0 || $src_y <= -$tmp_img_h || $src_y > $src_img_h) { $src_y = $src_h = $dst_y = $dst_h = 0; } else if ($src_y <= 0) { $dst_y = -$src_y; $src_y = 0; $src_h = $dst_h = min($src_img_h, $tmp_img_h + $src_y); } else if ($src_y <= $src_img_h) { $dst_y = 0; $src_h = $dst_h = min($tmp_img_h, $src_img_h - $src_y); } // Scale to destination position and size $ratio = $tmp_img_w / $dst_img_w; $dst_x /= $ratio; $dst_y /= $ratio; $dst_w /= $ratio; $dst_h /= $ratio; $dst_img = imagecreatetruecolor($dst_img_w, $dst_img_h); // Add transparent background to destination image imagefill($dst_img, 0, 0, imagecolorallocatealpha($dst_img, 0, 0, 0, 127)); imagesavealpha($dst_img, true); $result = imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); if ($result) { if (!imagepng($dst_img, $dst)) { $this -> msg = "Failed to save the cropped image file"; } } else { $this -> msg = "Failed to crop the image file"; } imagedestroy($src_img); imagedestroy($dst_img); } } private function codeToMessage($code) { $errors = array( UPLOAD_ERR_INI_SIZE =>'The uploaded file exceeds the upload_max_filesize directive in php.ini', UPLOAD_ERR_FORM_SIZE =>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', UPLOAD_ERR_PARTIAL =>'The uploaded file was only partially uploaded', UPLOAD_ERR_NO_FILE =>'No file was uploaded', UPLOAD_ERR_NO_TMP_DIR =>'Missing a temporary folder', UPLOAD_ERR_CANT_WRITE =>'Failed to write file to disk', UPLOAD_ERR_EXTENSION =>'File upload stopped by extension', ); if (array_key_exists($code, $errors)) { return $errors[$code]; } return 'Unknown upload error'; } public function getResult() { return !empty($this -> data) ? $this -> dst : $this -> src; } public function getMsg() { return $this -> msg; } } $crop = new CropAvatar( isset($_POST['avatar_src']) ? $_POST['avatar_src'] : null, isset($_POST['avatar_data']) ? $_POST['avatar_data'] : null, isset($_FILES['avatar_file']) ? $_FILES['avatar_file'] : null ); $response = array( 'state' => 200, 'message' => $crop -> getMsg(), 'result' => $crop -> getResult() ); echo json_encode($response);
Dari kedua koding di atas mungkin sudah sedikit jelas ya kawan karena memang sudah sangat jelas dari setiap koding yang saya buat untuk membuat sebuah fungsi cropper gambar.
Source Code
Untuk mengunduh source code nya. Klik Disini
Sekian untuk catatan kali ini. Semoga catatan ini bisa bermanfaat. Apabila ada yang ingin ditanyakan, langsung tanyakan saja lewat form komentar dibawah ini. Terimakasih.
Sumber & Referensi
Dokumentasi Bootstrap : http://getbootstrap.com/getting-started/
JQuery Cropper : https://fengyuanchen.github.io/cropper
Cara Mudah Membuat Crop Gambar Plus Upload dengan PHP, Tutorial Membuat Crop Gambar Plus Upload dengan PHP, Tutorial membuat Crop dan Upload gambar dengan PHP, Cara Membuat Crop dan Upload Gambar dengan PHP, Tutorial membuat Upload dan Crop gambar dengan PHP, Cara Membuat Upload dan Crop gambar dengan PHP
POST YOUR COMMENTS