如何使用 cropper.js 对图像进行裁剪?

3

我正在尝试学习如何使用cropper.js,目前看起来效果不错,但是...当我尝试裁剪图片时,如何将结果放回到我的表单中呢?

我的输入框的id为'profile_avatar'。所以我尝试把更新后的图像放在那里,但无法实现。

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

但是当我点击“剪切”按钮时,控制台会显示:

InvalidStateError: 尝试使用一个不可用的对象或已失效的对象

我做错了什么?我已经折腾了几个小时了。非常感谢!

带视图的slim文件:

  = 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>

请添加包括 #cut_button#profile_avatar 的 HTML 标记。 - Ed Lucas
@EdLucas,已添加。 - Ruslan Valeev
没有设置“裁剪器”对象的 JavaScript,很难说清楚。此外,你能确定哪一行JS代码导致了错误吗? - Ed Lucas
@EdLucas 添加了JS并标注了错误位置。 - Ruslan Valeev
2个回答

1

有一件事情需要注意,那就是你需要将图像的源设置为toDataUrl()的输出。例如:

HTML:

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

JS:

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

您可以使用JavaScript实时创建该图像,或者在标记中包含<img/>标签,其中包含空白图像或隐藏图像(在添加裁剪后显示它)。
要在表单中传递图像,应使用输入字段,因为此时值为字符串(例如“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby”)。
HTML:
<input id="cropped_image" type="hidden" />

JS:

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

是的,但它将是一个图像标签,对吧?我指的是如何将其发送到服务器? - Ruslan Valeev
抱歉,我误解了你的意图。我认为你只需要使用不同的字段类型,因为图片已经被toDataUrl()转换成了字符串。请参考上面的内容。 - Ed Lucas
<input type="file" /> 是用于文件上传的特定代码。请参阅: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file - Ed Lucas
即使使用 toBlob() 创建图像“文件”,也无法在此表单中使用,因为您无法以编程方式设置 <input type="file" /> 的值:如何在HTML中为文件输入设置值? - Ed Lucas
那么也许只能通过ajax实现?就像这里说的一样?在Rails上裁剪图像 - Ruslan Valeev
显示剩余2条评论

0

如果您的服务器需要文件作为输入,请检查此链接

整个过程如下: CroppedData() -> Base64 图像 -> Blob -> 文件 ===> 发送到服务器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接