HTML5画布drawImage大小调整问题

HTML5 Canvas drawImage resizing issues

本文关键字:调整 问题 画布 drawImage HTML5      更新时间:2023-09-26

当我使用drawImage调整从精灵表上特定位置提取的图像的大小时,它看起来好像drawImage有时会拉到源x+源y/swidth+右边界之外。

下面的jfiddle说明了正在发生的事情:https://jsfiddle.net/cxuxyLj2/

相关代码如下:

drawingSurface.drawImage(heroSprite, 0, 64, 32, 64, 20, 144, 32, 64);
drawingSurface.drawImage(heroSprite, 0, 64, 32, 64, 20+50, 144, 32*2, 64*2);

有一些线显示在RESIZE精灵的头部上方(可能是拉动第一行上相同角色的鞋子),但不是原始精灵的头部。

我的问题是,是否可以确认这是一个合法的drawImage错误,或者我做错了什么?

这实际上是因为在重新缩放精灵时使用了反别名
因为你确实在一个循环中绘制,而从来没有清除上下文,所以反别名工件变得越来越大:

var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");
var heroSprite = new Image();
heroSprite.src = "http://gopus.xepher.net/game/gfx/herosprite7.png";
render();
function render () {
	setTimeout(render, 1000);
	drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20, 25, 32, 64);
	drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20+50, 25, 32*2, 64*2);
	drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 150.6666687774, 25.33333222227, 32,64);
}
<canvas width="400" height="400" style="border:1px solid #000"></canvas>

您可以通过将imageSmoothingEnabled标志设置为false来避免它,但在10。。。

var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");
drawingSurface.mozImageSmoothingEnabled = false;
drawingSurface.webkitImageSmoothingEnabled = false;
drawingSurface.msImageSmoothingEnabled = false;
drawingSurface.imageSmoothingEnabled = false;
var heroSprite = new Image();
heroSprite.src = "http://gopus.xepher.net/game/gfx/herosprite7.png";
render();
function render() {
  setTimeout(render, 16);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20, 25, 32, 64);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20 + 50, 25, 32 * 2, 64 * 2);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 150.6666687774, 25.33333222227, 32, 64);
}
<canvas width="400" height="400" style="border:1px solid #000"></canvas>

或者通过在每次调用时清除画布,可以避免工件生长,但仍然会有自然的工件。。。

var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");
var heroSprite = new Image();
heroSprite.src = "http://gopus.xepher.net/game/gfx/herosprite7.png";
render();
function render() {
  setTimeout(render, 16);
  drawingSurface.clearRect(0,0,canvas.width, canvas.height);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20, 25, 32, 64);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 20 + 50, 25, 32 * 2, 64 * 2);
  drawingSurface.drawImage(heroSprite, 0, 32, 32, 64, 150.6666687774, 25.33333222227, 32, 64);
}
<canvas width="400" height="400" style="border:1px solid #000"></canvas>

因此,最终的解决方案是使用缓冲画布,只以正常比例绘制精灵(减少抗锯齿),然后重新绘制这个缓冲区画布按所需的比例,你会保留图像中的抗锯齿伪影,但不会再吃掉裁剪区域的边界:

var canvas = document.querySelector("canvas");
var drawingSurface = canvas.getContext("2d");
var heroSprite = new Image();
heroSprite.src = "http://gopus.xepher.net/game/gfx/herosprite7.png";
var spriteCanvas = document.createElement('canvas');
var spriteCtx = spriteCanvas.getContext('2d');
var croppedSprite = function(x, y, width, height){
  spriteCanvas.width = width;
  spriteCanvas.height = height;
  spriteCtx.drawImage(heroSprite, x, y, width, height, 0,0, width, height);
  return spriteCanvas;
  }
render();
function render() {
  setTimeout(render, 16);
  drawingSurface.drawImage(croppedSprite(0, 64, 32, 64), 20, 25, 32, 64);
  drawingSurface.drawImage(croppedSprite(0, 64, 32, 64), 20 + 50, 25, 32 * 2, 64 * 2);
  drawingSurface.drawImage(croppedSprite(0, 64, 32, 64), 150.6666687774, 25.33333222227, 32, 64);
}
<canvas width="400" height="400" style="border:1px solid #000"></canvas>

此外,你应该在精灵之间增加更多的空间。