【问题标题】:Whole image won't be drawn on canvas in JavaScript整个图像不会在 JavaScript 中绘制在画布上
【发布时间】:2021-05-05 23:46:12
【问题描述】:

我正在制作一个照片编辑器,您可以在其中选择上传将在画布上绘制的图像。我让用户在不刷新网站的情况下上传新图片。但是,第二次尝试上传不同的图像时,整个图像将不会绘制在画布上。唯一要绘制的部分是用户在此之前上传的图像的大小。这很奇怪,因为每次用户上传新图片时都会设置新尺寸。

经过反复试验,我发现新的画布大小实际上设置为上传图像的大小。但是,它仍然不会绘制整个图像,即使指定图像应该以画布的大小绘制。因此,问题在于绘制图像的线条,而不是设置画布大小的部分。我尝试绘制图像两次而不是一次,只是为了看看会发生什么。它确实有效,即使用于绘制图像的两条线是相同的。我觉得这很奇怪,我觉得这不是解决问题的正确方法。

这是加载图片的部分代码:

var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');

var img;
var ratio;

var overlay = document.getElementById("overlay")

canvas.width = 400;

function handleImage(e){
  var reader = new FileReader();
  reader.onload = function(event){
    img = new Image();
    img.onload = function(){
      ratio = this.height / this.width;
      canvas.height = canvas.width * ratio;
      ctx.drawImage(img,0,0,canvas.width, canvas.height);
    }
    overlay.style = "display: none;"
    img.src = event.target.result;
    window.onbeforeunload = function() {
      return true;
    };
  }
  reader.readAsDataURL(e.target.files[0]);
}
canvas { border: 1px solid; }
<input type="file" id="imageLoader">
<canvas id="imageCanvas"></canvas>
<div id="overlay">Unrelated overlay...</div>

【问题讨论】:

  • 我根据您提供的内容制作了一个实时 sn-p,但这不允许重现声称的问题。请提供minimal reproducible example
  • 放弃不必要的 FileReader 并执行 img.src = URL.createObjectURL(event.target.files[0])

标签: javascript html canvas


【解决方案1】:

你得到的行为并不奇怪,但非常有意义,因为你应该将画布的大小调整为每次加载的图像的自然尺寸!

是什么让您认为画布会自动调整自己以适应任何加载的图像?

您需要在每次加载新图像时执行此操作...

canvas.width=img.naturalWidth;
canvas.height=img.naturalHeight;
canvas.style.transform='scale(0.5,0.5)';

【讨论】:

  • 我认为您不太了解我的帖子。我使用比率将画布按比例缩放到图像尺寸的任何大小。我已经检查了画布是否已调整为图像的大小,并且确实如此。但是,绘制的图像并没有填满整个画布,并且图像看起来被裁剪了。
  • 如果要缩放包括画布在内的元素,我会使用... canvas.style.transform='scale(x,y)';不要手动缩放,让计算机为您计算!
  • 这是我的问题。设置画布大小的方法有很多。让我好奇的是,为什么ctx设置成画布大小时不会填满整个画布,而画布的尺寸和图片一样。
  • 不要手动缩放,让电脑帮你计算!
【解决方案2】:

一段时间后,我发现在重绘图像之前我必须使用clearRect

现在 JavaScript 代码如下所示:

var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');

var img;
var ratio;

var overlay = document.getElementById("overlay")

canvas.width = 400;

function handleImage(e){
  var reader = new FileReader();
  reader.onload = function(event){
    img = new Image();
    img.onload = function(){
      ratio = this.height / this.width;
      canvas.height = canvas.width * ratio;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img,0,0,canvas.width, canvas.height);
    }
    overlay.style = "display: none;"
    img.src = event.target.result;
    window.onbeforeunload = function() {
      return true;
    };
  }
  reader.readAsDataURL(e.target.files[0]);
}

【讨论】:

  • 不,设置画布宽度或高度,即使是相同的值,也会重置上下文并清除其位图缓冲区,clearRect 在这里根本没有帮助。请编辑您的问题,以便我们可以在那里重现该问题。
  • 我尝试制作一个缩短版,但由于某种原因它不起作用。但是,clearRect 似乎已经为我解决了这个问题,因为现在一切正常。
  • 我敢打赌,如果你评论 clearRect 行,它仍然可以工作。再一次,这个 clearRect 在这里是无操作的,因为你改变了画布的高度。
猜你喜欢
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 2018-12-09
  • 1970-01-01
  • 2017-02-15
  • 2012-01-14
相关资源
最近更新 更多