web-dev-qa-db-ja.com

Dropzone.jsがサーバーに画像を送信する前にcropper.jsを使用する

ここでやりたいのは、Dropzone.jsがドロップされた画像をサーバーに送信する前に、ユーザーが画像をトリミングできるように、cropper.js(fengyuanchenスクリプト)でモーダルが表示され、画像がトリミングされたら、Dropzone.jsで送信します。サーバーに。

したがって、#cropboxの画像srcを関数fileToBase64で変更し、クロッパーの画像を関数cropper( 'replace')に置き換えると、ユーザーからアップロードされた新しい画像ではなく、default.jpg画像が表示され続けます。

HTML

<div class="wrapper-crop-box">
    <div class="crop-box">
        <img src="default.jpg" alt="Cropbox" id="cropbox">
    </div>
</div>

JS:

function fileToBase64(file) {
  var preview = document.querySelector('.crop-box img');
  var reader  = new FileReader();

  reader.onloadend = function () {
    preview.src = reader.result;
  }

  if (file) {
    reader.readAsDataURL(file);
  } else {
    preview.src = "";
  }
}

$(function() {
    Dropzone.options.avtDropzone = {
        acceptedFiles: 'image/*',
        autoProcessQueue: true,
        paramName: 'file',
        maxFilesize: 2,
        maxFiles: 1,
        thumbnailWidth: 200,
        thumbnailHeight: 200,
        accept: function(file, done) {
            fileToBase64(file); 
            $('#cropbox').cropper('replace', $('#cropbox').attr('src'));
            $('.wrapper-crop-box').fadeIn();
            done();
        },
        init: function() {
            this.on("addedfile", function(file) {
                if (this.files[1]!=null){
                    this.removeFile(this.files[0]);
                }
            });
        }
    };

    $('#cropbox').cropper({
      aspectRatio: 1 / 1,
      resizable: false,
      guides: false,
      dragCrop: false,
      autoCropArea: 0.4,
      checkImageOrigin: false,
      preview: '.avatar'
    });
});
12
Fosfor

あなたはおそらくもうそれを必要としないでしょう、しかし私はそれをここに残しておきます:)

それは少しトリッキーで、私の解決策はおそらく「ハック」ですが、それは機能し、サイズを変更するためにサーバーにファイルをアップロードする必要はありません。

モーダルウィンドウでもクロッパーを使用しています。サーバーにアップロードする前に、ユーザーに画像を特定のサイズにトリミングするように強制したかったのです。

モーダル画像のトリミングを確認すると、すぐにアップロードされます。

// 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' });
}

// modal window template
var modalTemplate = '<div class="modal"><!-- bootstrap modal here --></div>';

// initialize dropzone
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone(
    "#my-dropzone-container",
    {
        autoProcessQueue: false,
        // ..your other parameters..
    }
);

// listen to thumbnail event
myDropzone.on('thumbnail', function (file) {
    // ignore files which were already cropped and re-rendered
    // to prevent infinite loop
    if (file.cropped) {
        return;
    }
    if (file.width < 800) {
        // validate width to prevent too small files to be uploaded
        // .. add some error message here
        return;
    }
    // cache filename to re-assign it to cropped file
    var cachedFilename = file.name;
    // remove not cropped file from dropzone (we will replace it later)
    myDropzone.removeFile(file);

    // dynamically create modals to allow multiple files processing
    var $cropperModal = $(modalTemplate);
    // 'Crop and Upload' button in a modal
    var $uploadCrop = $cropperModal.find('.crop-upload');

    var $img = $('<img />');
    // initialize FileReader which reads uploaded file
    var reader = new FileReader();
    reader.onloadend = function () {
        // add uploaded and read image to modal
        $cropperModal.find('.image-container').html($img);
        $img.attr('src', reader.result);

        // initialize cropper for uploaded image
        $img.cropper({
            aspectRatio: 16 / 9,
            autoCropArea: 1,
            movable: false,
            cropBoxResizable: true,
            minContainerWidth: 850
        });
    };
    // read uploaded file (triggers code above)
    reader.readAsDataURL(file);

    $cropperModal.modal('show');

    // listener for 'Crop and Upload' button in modal
    $uploadCrop.on('click', function() {
        // get cropped image data
        var blob = $img.cropper('getCroppedCanvas').toDataURL();
        // transform it to Blob object
        var newFile = dataURItoBlob(blob);
        // set 'cropped to true' (so that we don't get to that listener again)
        newFile.cropped = true;
        // assign original filename
        newFile.name = cachedFilename;

        // add cropped file to dropzone
        myDropzone.addFile(newFile);
        // upload cropped file with dropzone
        myDropzone.processQueue();
        $cropperModal.modal('hide');
    });
});
10
Maria Petrunina

これがこの機能を提供する要点です。

https://Gist.github.com/maria-p/8633b51f629ea8dbd27e

// 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' });
}

// modal window template
var modalTemplate = '<div class="modal"><!-- bootstrap modal here --></div>';

// initialize dropzone
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone(
    "#my-dropzone-container",
    {
        autoProcessQueue: false,
        // ..your other parameters..
    }
);

// listen to thumbnail event
myDropzone.on('thumbnail', function (file) {
    // ignore files which were already cropped and re-rendered
    // to prevent infinite loop
    if (file.cropped) {
        return;
    }
    if (file.width < 800) {
        // validate width to prevent too small files to be uploaded
        // .. add some error message here
        return;
    }
    // cache filename to re-assign it to cropped file
    var cachedFilename = file.name;
    // remove not cropped file from dropzone (we will replace it later)
    myDropzone.removeFile(file);

    // dynamically create modals to allow multiple files processing
    var $cropperModal = $(modalTemplate);
    // 'Crop and Upload' button in a modal
    var $uploadCrop = $cropperModal.find('.crop-upload');

    var $img = $('<img />');
    // initialize FileReader which reads uploaded file
    var reader = new FileReader();
    reader.onloadend = function () {
        // add uploaded and read image to modal
        $cropperModal.find('.image-container').html($img);
        $img.attr('src', reader.result);

        // initialize cropper for uploaded image
        $img.cropper({
            aspectRatio: 16 / 9,
            autoCropArea: 1,
            movable: false,
            cropBoxResizable: true,
            minContainerWidth: 850
        });
    };
    // read uploaded file (triggers code above)
    reader.readAsDataURL(file);

    $cropperModal.modal('show');

    // listener for 'Crop and Upload' button in modal
    $uploadCrop.on('click', function() {
        // get cropped image data
        var blob = $img.cropper('getCroppedCanvas').toDataURL();
        // transform it to Blob object
        var newFile = dataURItoBlob(blob);
        // set 'cropped to true' (so that we don't get to that listener again)
        newFile.cropped = true;
        // assign original filename
        newFile.name = cachedFilename;

        // add cropped file to dropzone
        myDropzone.addFile(newFile);
        // upload cropped file with dropzone
        myDropzone.processQueue();
        $cropperModal.modal('hide');
    });
});

注意してください、私は著者ではありません。

1
TWilly

JQueryの依存関係を望まない、または持つことができない開発者向け。

私は最近 DropzoneとCropper.jsの統合に関する記事 を書きました、それは役に立つかもしれません。以下の記事のコードスニペットを参照してください。

HTML

<div class="dropzone" id="myDropzone"></div>

JavaScript

Dropzone.options.myDropzone = {
    url: '/post',
    transformFile: function(file, done) {

        var myDropZone = this;

        // Create the image editor overlay
        var editor = document.createElement('div');
        editor.style.position = 'fixed';
        editor.style.left = 0;
        editor.style.right = 0;
        editor.style.top = 0;
        editor.style.bottom = 0;
        editor.style.zIndex = 9999;
        editor.style.backgroundColor = '#000';

        // Create the confirm button
        var confirm = document.createElement('button');
        confirm.style.position = 'absolute';
        confirm.style.left = '10px';
        confirm.style.top = '10px';
        confirm.style.zIndex = 9999;
        confirm.textContent = 'Confirm';
        confirm.addEventListener('click', function() {

            // Get the canvas with image data from Cropper.js
            var canvas = cropper.getCroppedCanvas({
                width: 256,
                height: 256
            });

            // Turn the canvas into a Blob (file object without a name)
            canvas.toBlob(function(blob) {

                // Update the image thumbnail with the new image data
                myDropZone.createThumbnail(
                    blob,
                    myDropZone.options.thumbnailWidth,
                    myDropZone.options.thumbnailHeight,
                    myDropZone.options.thumbnailMethod,
                    false, 
                    function(dataURL) {

                        // Update the Dropzone file thumbnail
                        myDropZone.emit('thumbnail', file, dataURL);

                        // Return modified file to dropzone
                        done(blob);
                    }
                );

            });

            // Remove the editor from view
            editor.parentNode.removeChild(editor);

        });
        editor.appendChild(confirm);

        // Load the image
        var image = new Image();
        image.src = URL.createObjectURL(file);
        editor.appendChild(image);

        // Append the editor to the page
        document.body.appendChild(editor);

        // Create Cropper.js and pass image
        var cropper = new Cropper(image, {
            aspectRatio: 1
        });

    }
};

統合コードのデモはここにあります: https://codepen.io/rikschennink/pen/PXQNGp?editors=001

1
Rik