简体   繁体   中英

How to apply cropping to image with cropper.js?

I'm trying to realize, how to use cropper.js, and so far it looks pretty good, but... when I trying to crop the image, how can I put the result back to my form?

My input has id 'profile_avatar'. So I try to put there updated image, and cannot.

$('#cut_button').click(function(e) {
  e.preventDefault();
  var croppedImageDataURL = cropper.getCroppedCanvas()
  $('#profile_avatar').val(croppedImageDataURL.toDataURL("image/png"))
});

But when I click 'cut button' I got

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

in console. What am I doing wrong? I'm trying to beat it few hours. Thank you so much!

slim file with view :

  = form_for @profile do |f|
    = f.label :avatar
      = f.file_field :avatar
      .canvas_window
        canvas id='canvas'
      .preview
      = link_to('Cut', '', id: 'cut_button')
      = f.label :photos
      = f.file_field :photos, multiple: true
      = f.label :description
      = f.text_area :description
      = @profile.errors.messages[:description].presence
      = hidden_field :dimensions, ''
      = f.submit I18n.t('user.forms.buttons.submit')

javascript:
  var canvas  = $("#canvas"),
      context = canvas.get(0).getContext("2d"),
      $result = $('#result');

  $('#profile_avatar').on( 'change', function(){
    console.log('start')
    if (this.files && this.files[0]) {
      if ( this.files[0].type.match(/^image\//) ) {
        var reader = new FileReader();
        reader.onload = function(evt) {
          var img = new Image();
          img.onload = function() {
            context.canvas.height = img.height;
            context.canvas.width  = img.width;
            context.drawImage(img, 0, 0);
            const image = document.getElementById('canvas');
            const cropper = new Cropper(image, {
              preview: '.preview',
              aspectRatio: 16 / 9,
              crop(event) {
                dimensions = event.detail.width + 'x' + event.detail.width + '+' + event.detail.x + '+' + event.detail.y
                $('#new_profile input#dimensions_').val(dimensions)
                console.log(dimensions);
                console.log(event.detail.x);
                console.log(event.detail.y);
                console.log(event.detail.width);
                console.log(event.detail.height);
              },
            });

            $('#cut_button').click(function(e) {
              e.preventDefault();
              var croppedImageDataURL = cropper.getCroppedCanvas()
              HERE IS ERROR \/
              $('#profile_avatar').val(croppedImageDataURL.toDataURL("image/png"))
              console.log(croppedImageDataURL.toDataURL("image/png"))
             });
           };
           img.src = evt.target.result;
        };
        reader.readAsDataURL(this.files[0]);
      }
      else {
        alert("Invalid file type! Please select an image file.");
      }
    }
    else {
      alert('No file(s) selected.');
    }
  });

html :

<form class="new_profile" id="new_profile" enctype="multipart/form-data" action="/profiles" accept-charset="UTF-8" method="post">
  <input type="hidden" name="authenticity_token" value="j53mqq1th1kb17ynj2jxIMcPFRC210EQVLBSgEu2n4FLOONtFBH3Vu7wrjc+iDrogn99H/emvN5qUdyZo2pAkg==">
  <label for="profile_avatar">Avatar</label>
  <input type="file" name="profile[avatar]" id="profile_avatar">
  <div class="canvas_window">
    <canvas id="canvas"></canvas>
  </div>
  <div class="preview"></div>
  <a id="cut_button" href="">Cut</a>
  <label for="profile_photos">Photos</label>
  <input multiple="multiple" type="file" name="profile[photos][]" id="profile_photos">
  <label for="profile_description">Description</label>
  <textarea name="profile[description]" id="profile_description"></textarea>
  <input type="hidden" name="dimensions[]" id="dimensions_">
  <input type="submit" name="commit" value="Submit" data-disable-with="Submit">
</form>

One thing that stands out is that you need to set the source of an image to the output of toDataUrl() . For example:

HTML:

<img id="cropped_image" src="/blank.gif"></img>

JS:

$("#cropped_image").attr("src", croppedImageDataURL.toDataURL("image/png"));

You could create that image on the fly with JavaScript or include the <img/> tag in your markup with a blank image or hidden (revealing it after you add the cropped image).

To pass the image in your form, you should use an input field because the value at this point is a string (eg "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby").

HTML:

<input id="cropped_image" type="hidden" />

JS:

$("#cropped_image").val(croppedImageDataURL.toDataURL("image/png"));

Check this link if your server need a File as input.

The overall process is: CroppedData() -> Base64 image -> Blob -> File ===> Send to Server

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM