如何在不使用 Ajax 的情况下使用 Cropper.js 编辑图像后上传图像?
HTML
<div class="block-content" id=profile-image>
<div class="row pb-3">
<div class="col-12">
<label>Profile Image</label>
<div class="options-container">
<img class="img-fluid options-item image-edit" id="image-place"
src="{{ $user->avatar ? asset(App\User::PROFILE_IMAGE_PATH . $user->avatar) : 'media/avatars/avatar-male.jpg' }}"
alt="Profile Image" style="max-width: 100%">
</div>
</div>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="reset" title="Reset">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="">
<span class="fa fa-sync-alt"></span>
</span>
</button>
<label class="btn btn-primary btn-upload" for="fileEdit" title="Upload image file">
<input type="file" class="sr-only" id="fileEdit" name="file" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff">
<input type="hidden" class="sr-only" id="hiddenBlob" name="hiddenBlob">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title=""
data-original-title="Import image with Blob URLs">
<span class="fa fa-upload"></span>
</span>
</label>
</div>
<div class="row">
<div class="col-12">
<div class="form-group text-center">
<button type="submit" class="btn btn-block btn-hero-lg btn-hero-primary">
<i class="si si-reload mr-1"></i> Update Profile
</button>
</div>
</div>
</div>
</div>
JS
$(function () {
'use strict';
let console = window.console || { log: function () { } }
let URL = window.URL || window.webkitURL;
let $image = $('.image-edit');
let $dataX = $('#dataX');
let $dataY = $('#dataY');
let $dataHeight = $('#dataHeight');
let $dataWidth = $('#dataWidth');
let $dataRotate = $('#dataRotate');
let $dataScaleX = $('#dataScaleX');
let $dataScaleY = $('#dataScaleY');
let options = {
aspectRatio: 16 / 9,
preview: '.img-preview',
crop: function (e) {
$dataX.val(Math.round(e.detail.x));
$dataY.val(Math.round(e.detail.y));
$dataHeight.val(Math.round(e.detail.height));
$dataWidth.val(Math.round(e.detail.width));
$dataRotate.val(e.detail.rotate);
$dataScaleX.val(e.detail.scaleX);
$dataScaleY.val(e.detail.scaleY);
}
}
let originalImageURL = $image.attr('src');
let uploadedImageName = 'cropped.jpg';
let uploadedImageType = 'image/jpeg';
let uploadedImageURL;
let cropper = new window.Cropper(document.getElementById('image-place'), options)
// Cropper
$image.on({
ready: function (e) {
// console.log(e.type);
},
cropstart: function (e) {
// console.log(e.type, e.detail.action);
},
cropmove: function (e) {
// console.log(e.type, e.detail.action);
},
cropend: function (e) {
// console.log(e.type, e.detail.action);
},
crop: function (e) {
cropper.getCroppedCanvas().toBlob(function(blob){
console.log(blob.text())
})
},
zoom: function (e) {
// console.log(e.type, e.detail.ratio);
}
}).cropper(options);
// Buttons
if (!$.isFunction(document.createElement('canvas').getContext)) {
$('button[data-method="getCroppedCanvas"]').prop('disabled', true);
}
if (typeof document.createElement('cropper').style.transition === 'undefined') {
$('button[data-method="rotate"]').prop('disabled', true);
$('button[data-method="scale"]').prop('disabled', true);
}
// Options
$('.docs-toggles').on('change', 'input', function () {
let $this = $(this);
let name = $this.attr('name');
let type = $this.prop('type');
let cropBoxData;
let canvasData;
if (!$image.data('cropper')) {
return;
}
if (type === 'checkbox') {
options[name] = $this.prop('checked');
cropBoxData = $image.cropper('getCropBoxData');
canvasData = $image.cropper('getCanvasData');
options.ready = function () {
$image.cropper('setCropBoxData', cropBoxData);
$image.cropper('setCanvasData', canvasData);
}
} else if (type === 'radio') {
options[name] = $this.val();
}
$image.cropper('destroy').cropper(options);
$image.cropper('getCroppedCanvas').toBlob(function (blob) {
console.log(blob);
})
});
// Methods
$('#profile-image').on('click', '[data-method]', function () {
let $this = $(this);
let data = $this.data();
let cropper = $image.data('cropper');
let cropped;
let $target;
let result;
if ($this.prop('disabled') || $this.hasClass('disabled')) {
return;
}
if (cropper && data.method) {
data = $.extend({}, data); // Clone a new one
if (typeof data.target !== 'undefined') {
$target = $(data.target);
if (typeof data.option === 'undefined') {
try {
data.option = JSON.parse($target.val());
} catch (e) {
console.log(e.message);
}
}
}
cropped = cropper.cropped;
switch (data.method) {
case 'rotate':
if (cropped && options.viewMode > 0) {
$image.cropper('clear');
}
break;
case 'getCroppedCanvas':
if (uploadedImageType === 'image/jpeg') {
if (!data.option) {
data.option = {}
}
data.option.fillColor = '#fff';
}
break;
}
result = $image.cropper(data.method, data.option, data.secondOption);
switch (data.method) {
case 'rotate':
if (cropped && options.viewMode > 0) {
$image.cropper('crop');
}
break;
case 'scaleX':
case 'scaleY':
$(this).data('option', -data.option);
break;
case 'getCroppedCanvas':
if (result) {
Swal.fire({
title: 'Info!',
html: result,
type: 'success',
})
}
break;
case 'destroy':
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
uploadedImageURL = '';
$image.attr('src', originalImageURL);
}
break;
}
if ($.isPlainObject(result) && $target) {
try {
$target.val(JSON.stringify(result));
} catch (e) {
console.log(e.message);
}
}
}
});
// Keyboard
$(document.body).on('keydown', function (e) {
if (e.target !== this || !$image.data('cropper') || this.scrollTop > 300) {
return;
}
switch (e.which) {
case 37:
e.preventDefault();
$image.cropper('move', -1, 0);
break;
case 38:
e.preventDefault();
$image.cropper('move', 0, -1);
break;
case 39:
e.preventDefault();
$image.cropper('move', 1, 0);
break;
case 40:
e.preventDefault();
$image.cropper('move', 0, 1);
break;
}
});
// Import image
let $inputImage = $('#fileEdit');
if (URL) {
$inputImage.change(function () {
let files = this.files;
let file;
if (!$image.data('cropper')) {
return;
}
if (files && files.length) {
file = files[0];
if (/^image\/\w+$/.test(file.type)) {
uploadedImageName = file.name;
uploadedImageType = file.type;
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
uploadedImageURL = URL.createObjectURL(file);
$image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
} else {
window.alert('Please choose an image file.');
}
}
});
} else {
$inputImage.prop('disabled', true).parent().addClass('disabled');
}
});