【问题标题】:HTML5 Canvas drawImage resizing issuesHTML5 Canvas drawImage 调整大小问题
【发布时间】:2016-01-02 11:07:27
【问题描述】:

当我使用 drawImage 从 spritesheet 上的特定位置拉出的图像调整大小时,似乎 drawImage 有时会拉到源 x + 源 y / swidth + sheight 边界之外。

下面的 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);

在 RESIZED sprite 的头部上方显示了一些线条(可能是在第一行拉同一角色的鞋子),但不是原始 sprite 的头部。

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

【问题讨论】:

  • 为了帖子的后代,您介意我将您的精灵表上传到 imgur 吗?

标签: javascript html canvas drawimage


【解决方案1】:

这实际上是因为重新缩放精灵时的抗锯齿。
因为您确实在循环中绘制,而没有清除上下文,所以抗锯齿伪影变得越来越大:

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 之前的 IE 不支持它...

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>

此外,您绝对应该在精灵之间添加更多空间。

【讨论】:

    猜你喜欢
    • 2014-07-24
    • 2013-02-17
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 2012-12-05
    • 1970-01-01
    相关资源
    最近更新 更多