我已使用https://gist.github.com/maria-p/8633b51f629ea8dbd27e处的代码作为在异步环境中将dropzone与cropperjs集成的基础,因此用户需要能够打开多个CRUD模式并上传/裁剪图像而不必刷新网页。
经过几天的研究,实验和撕下我剩下的小毛发,我有了一个脚本,该脚本现在对于上载和裁剪的第一张图片可以100%完美地工作,但是在随后的上载之前存在一些问题任何页面刷新。后续的上载导致控制台错误“ 无法读取null的属性'insertBefore'”,该错误与以下cropperjs代码片段有关:
key: "build",
value: function() {
if (this.sized && !this.ready) {
var A = this.element
, t = this.options
, e = this.image
, s = A.parentNode
, n = document.createElement("div");
n.innerHTML = '<div class="cropper-container" ... >';
var r = n.querySelector("." + D + "-container")
//[snip]
s.insertBefore(r, A.nextSibling) // <<<<<<<<<<<< this line
...换句话说,即使元素周围的代码似乎工作正常,也无法找到该元素的父节点,因为出现了裁剪器工具。仅控制台错误并没有什么大不了的,但它可以明确指出其他问题,因为图像旋转和翻转按钮的行为异常(在后续上传中),除非同一图像连续连续上传三次。我还注意到,出于某种原因,我从dropzone得到了两个“成功”响应,但仅当上传后续图像时才如此。所有上传均成功,只是操作按钮在第一个操作后不起作用。
有人可以帮助我解决此问题吗?我认为很重要的代码如下:
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function() {
cropperModal.modal('show');
cropperModal.on('shown.bs.modal', function() {
var image = $('<img/>');
cropperModal.find('.image-container').html(image);
image.attr('src', reader.result).attr('id', 'cropper-image');
cropper = new Cropper(document.getElementById('cropper-image'), {
autoCropArea: 1,
aspectRatio: imgRatio,
ready: function () {
myDropzone.removeFile(file);
}
});
});
};
...但是为了防万一,这是我完整的脚本(基于this):
// configure the upload routine
var imgRatio = 1.618; // aspect ratio of the saved images
var imgWidth = 600; // fixed width of the saved images (pix)
var imgQuality = 0.9; // quality of the saved image (e.g. 0.9)
var maxUpload = 5; // maximum uploaded file size (MB)
// transform cropper dataURI output to a Blob which Dropzone accepts
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: 'image/jpeg' });
}
// initialize dropzone
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone('#dropzone1', {
url: '/foo/bar/',
autoProcessQueue: false,
uploadMultiple: false,
maxFilesize: maxUpload,
dictDefaultMessage: '!{$labels["pic_upload"]}',
acceptedFiles: '.png, .jpg, .jpeg, .gif',
addRemoveLinks: true,
init: function() {
myDropzone = this;
this.on("success", function(file, responseText) {
console.log('Success responseText = ' + responseText);
if (responseText == 'success') {
// show success dialogue
swal({ title: '#{$labels["upload_success"]}', timer: 3000, icon: 'success', buttons: false });
} else {
// show error dialogue
swal({ title: '!{$labels["upload_error"]}', text: '"' + responseText + '"', icon: 'error' });
}
});
this.on("error", function (file, errorMessage) {
console.log('Error file = ' + JSON.stringify(file, null, 4));
console.log('Error errorMessage = ' + errorMessage);
swal({ title: '!{$labels["upload_error"]}', text: '"' + errorMessage + '"', icon: 'error' });
});
}
});
// listen to thumbnail event
myDropzone.on('thumbnail', function (file) {
// ignore files already cropped to prevent infinite loop
if (file.cropped) {
return;
}
// add the original filename to the dropzone URL (for recording in the file upload log)
myDropzone.options.url = '/foo/bar/' + encodeURIComponent(file.name);
// check the file extension type
var re = /(?:\.([^.]+))?$/;
var ext = re.exec(file.name)[1];
ext = ext.toUpperCase();
if (ext != "JPG" && ext != "JPEG" && ext != "GIF" && ext != "PNG") {
swal({ title: '!{$labels["upload_wrongext"]}', icon: 'error' });
return;
}
// prevent the upload if the file is too small
if (file.width < 400) {
swal({ title: '!{$labels["upload_toosmall"]}', icon: 'error' });
return;
}
// check the filesize does not exceed the maximum allowed
if (file.size > (maxUpload*1000000)) {
swal({ title: '!{$labels["upload_toolarge"]}', icon: 'error' });
return;
}
// target all required modal elements
var cropperModal = $('#cropper-modal');
var rotateLButton = cropperModal.find('.rotate-left');
var rotateRButton = cropperModal.find('.rotate-right');
var scaleXButton = cropperModal.find('.scale-x');
var scaleYButton = cropperModal.find('.scale-y');
var resetButton = cropperModal.find('.reset');
var uploadButton = cropperModal.find('.crop-upload');
// initialize FileReader and read uploaded file
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function() {
// open the bootstrap modal
cropperModal.modal('show');
// initialize cropper.js after the modal has loaded
cropperModal.on('shown.bs.modal', function() {
// load the submitted image ready for cropping
var image = $('<img/>');
cropperModal.find('.image-container').html(image);
image.attr('src', reader.result).attr('id', 'cropper-image');
// initialize cropper.js (must use native js targeting)
cropper = new Cropper(document.getElementById('cropper-image'), {
autoCropArea: 1,
aspectRatio: imgRatio,
ready: function () {
// remove un-cropped thumbnail from dropzone
myDropzone.removeFile(file);
}
});
});
};
// carry out image manipulation actions
// putting these functions inside the 'ready' makes no difference to the error issue
rotateLButton.on('click', function() {
cropper.rotate(90);
});
rotateRButton.on('click', function() {
cropper.rotate(-90);
});
scaleXButton.on('click', function() {
var $this = $(this);
cropper.scaleX($this.data('value'));
$this.data('value', -$this.data('value'));
});
scaleYButton.on('click', function() {
var $this = $(this);
cropper.scaleY($this.data('value'));
$this.data('value', -$this.data('value'));
});
resetButton.on('click', function() {
cropper.reset();
});
uploadButton.on('click', function() {
// get cropped image data
var blob = cropper.getCroppedCanvas( { width: imgWidth } ).toDataURL('image/jpeg', imgQuality);
// transform it to Blob object
var newFile = dataURItoBlob(blob);
// set 'cropped to true' so that we don't hit that listener again
newFile.cropped = true;
// assign resource ID as filename
newFile.name = 'foobar.jpg';
// add cropped file to dropzone
myDropzone.addFile(newFile);
// upload cropped file with dropzone
myDropzone.processQueue();
// close the cropper modal
cropperModal.modal('hide');
});
// remove thumbnail after upload to server
myDropzone.on('complete', function(file) {
myDropzone.removeFile(file);
});
});
依赖关系:cropperjs 1.4.0; Dropzone 5.4.0; jQuery 3.3.1;铬67.0.3396.87