0
votes

I am using https://github.com/fengyuanchen/cropperjs/ but it has a problem in getCroppedCanvas function , It's working just fine with small images but not showing when it comes to larger images

result.appendChild(cropper.getCroppedCanvas());

I am using this live example https://fengyuanchen.github.io/cropperjs/examples/upload-cropped-image-to-server.html; source code:

<!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">
  <title>Cropper.js</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css">
  <link rel="stylesheet" href="../css/cropper.css">
  <style>
    .label {
      cursor: pointer;
    }

    .progress {
      display: none;
      margin-bottom: 1rem;
    }

    .alert {
      display: none;
    }

    .img-container img {
      max-width: 100%;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>Upload cropped image to server</h1>
    <label class="label" data-toggle="tooltip" title="Change your avatar">
      <img class="rounded" id="avatar" src="https://avatars0.githubusercontent.com/u/3456749?s=160" alt="avatar">
      <input type="file" class="sr-only" id="input" name="image" accept="image/*">
    </label>
    <div class="progress">
      <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
    </div>
    <div class="alert" role="alert"></div>
    <div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="modalLabel">Crop the image</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <div class="img-container">
              <img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
            <button type="button" class="btn btn-primary" id="crop">Crop</button>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.bundle.min.js"></script>
  <script src="https://fengyuanchen.github.io/cropperjs/js/cropper.js"></script>
  <script>
    window.addEventListener('DOMContentLoaded', function () {
      var avatar = document.getElementById('avatar');
      var image = document.getElementById('image');
      var input = document.getElementById('input');
      var $progress = $('.progress');
      var $progressBar = $('.progress-bar');
      var $alert = $('.alert');
      var $modal = $('#modal');
      var cropper;

      $('[data-toggle="tooltip"]').tooltip();

      input.addEventListener('change', function (e) {
        var files = e.target.files;
        var done = function (url) {
          input.value = '';
          image.src = url;
          $alert.hide();
          $modal.modal('show');
        };
        var reader;
        var file;
        var url;

        if (files && files.length > 0) {
          file = files[0];

          if (URL) {
            done(URL.createObjectURL(file));
          } else if (FileReader) {
            reader = new FileReader();
            reader.onload = function (e) {
              done(reader.result);
            };
            reader.readAsDataURL(file);
          }
        }
      });

      $modal.on('shown.bs.modal', function () {
        cropper = new Cropper(image, {
          aspectRatio: 1,
          viewMode: 3,
        });
      }).on('hidden.bs.modal', function () {
        cropper.destroy();
        cropper = null;
      });

      document.getElementById('crop').addEventListener('click', function () {
        var initialAvatarURL;
        var canvas;

        $modal.modal('hide');

        if (cropper) {
          canvas = cropper.getCroppedCanvas({
            width: 160,
            height: 160,
          });
          initialAvatarURL = avatar.src;
          avatar.src = canvas.toDataURL();
          $progress.show();
          $alert.removeClass('alert-success alert-warning');
          canvas.toBlob(function (blob) {
            var formData = new FormData();

            formData.append('avatar', blob, 'avatar.jpg');
            $.ajax('https://jsonplaceholder.typicode.com/posts', {
              method: 'POST',
              data: formData,
              processData: false,
              contentType: false,

              xhr: function () {
                var xhr = new XMLHttpRequest();

                xhr.upload.onprogress = function (e) {
                  var percent = '0';
                  var percentage = '0%';

                  if (e.lengthComputable) {
                    percent = Math.round((e.loaded / e.total) * 100);
                    percentage = percent + '%';
                    $progressBar.width(percentage).attr('aria-valuenow', percent).text(percentage);
                  }
                };

                return xhr;
              },

              success: function () {
                $alert.show().addClass('alert-success').text('Upload success');
              },

              error: function () {
                avatar.src = initialAvatarURL;
                $alert.show().addClass('alert-warning').text('Upload error');
              },

              complete: function () {
                $progress.hide();
              },
            });
          });
        }
      });
    });
  </script>
</body>
</html>

the cropper script is in: https://fengyuanchen.github.io/cropperjs/js/cropper.js

2
I had a similar problem with cropper and couldn't resolve the issue. I ended up switching to croppiejs instead, which works really good.silencedogood
Could be related to this issue: "For very very big images, you may have to upload them to server-side to crop them, as most of browsers have memory limit.".showdev
@silencedogood do you have a crop and upload example, I am reading Croppie js documentation but I don't see a upload example and a canvas preview after croppedOtávio Barreto
Yes I can give an example... But there are plenty of docs and I'm not sure if it's appropriate to post a technically non-answer. But w/e I'll post it anyways to help you out. However, how big is this image that's giving you trouble?silencedogood
the image is 1279x853 pixel, 1,50 mb, uploading fine on server, but not showing preview on canvasOtávio Barreto

2 Answers

2
votes

Using croppiejs helped me solve this issue. To utilize Croppie with a preview, you just set the value of an html image element to croppie's base64 result:

First create croppie instance:

var cropperlg = new Croppie(document.getElementById('croppie-lg'), {
    viewport: {
        width: 400
        height: 800
    },
    boundary: {
        height: 500
        width: 1000
    }
});

This bit of code binds croppie to an image and executes the crop on click. EDIT: I simplified the code for a more basic example.

cropperlg.bind({
    url: '/images/someimg.jpg'
});

$('#crop-btn').on('click', (e) => {
    cropperlg.result({
        type: 'canvas',
        size: { width: 1000, height: 400 }
    }).then(function(result) {
        $('#cropped-img').attr('src', result);
    })
});

You should be able to figure it out from here.

0
votes

this worked for me

var cropper = $('#cropper-image').cropper('getCroppedCanvas', {
                // Limit max sizes
                  maxWidth: 4096,
                  maxHeight: 4096,
              });

After setting this, it worked well on both mobile and desktop.