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'));
});
});
- (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'));
- });
- });
(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>
- <!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>
<!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);
- <?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);
<?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
Crop
(Total : 6,549 viewers, 1 viewers today)
POST YOUR COMMENTS TO Prozoila (Cancel)