HTML5 - Canvas,drawImage()绘制图像模糊

Zen*_*eng 14 javascript html5 canvas

我试图将以下图像绘制到画布上,但尽管定义了画布的大小,但它看起来很模糊.正如您在下面看到的,图像清晰而清晰,而在画布上,图像模糊且像素化.

在此输入图像描述

这是它的外观(左边是原始的,右边是绘制的画布,模糊不清.)

在此输入图像描述

我究竟做错了什么?

console.log('Hello world')

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32

playerImg.onload = function() {
  ctx.drawImage(playerImg, 0, 0, 32, 32);
};
Run Code Online (Sandbox Code Playgroud)
#canvas {
  background: #ABABAB;
  position: relative;
  height: 352px;
  width: 512px;
  z-index: 1;
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="352" width="521"></canvas>
Run Code Online (Sandbox Code Playgroud)

Can*_*vas 22

发生这种情况的原因是抗锯齿.只需将其设置imageSmoothingEnabled为false即可

context.imageSmoothingEnabled = false;
Run Code Online (Sandbox Code Playgroud)

这是一个jsFiddle版本

jsFiddle:https://jsfiddle.net/mt8sk9cb/

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'

playerImg.onload = function() {
  ctx.imageSmoothingEnabled = false;
  ctx.drawImage(playerImg, 0, 0, 256, 256);
};
Run Code Online (Sandbox Code Playgroud)

  • 您应该添加供应商前缀,因为这不是稳定属性. (2认同)

Kai*_*ido 12

您的问题是您canvas{width:512}对canvas属性的css约束width=521将使您的浏览器重新取样整个画布.

要避免它,请删除那些css声明.

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32

playerImg.onload = function() {
  ctx.drawImage(playerImg, 0, 0, 32, 32);
};
Run Code Online (Sandbox Code Playgroud)
#canvas {
  background: #ABABAB;
  position: relative;
  z-index: 1;
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="352" width="521"></canvas>
Run Code Online (Sandbox Code Playgroud)

此外,如果您要重新采样图像(从32x32到其他尺寸),@ scan的解决方案将是最佳选择.

  • @DanF你可以按照自己的意愿处理接受的标记,但由于canvas'one没有解决你的问题,这是由CSS声明造成的,我认为未来的读者接受这个并给出一个更好的赏金给画布' (2认同)
  • +100,因为我把`ctx.imageSmoothingEnabled = false;` 放到这里之后,但是图像仍然模糊。 (2认同)

Din*_*den 7

当我针对我的一些问题遇到这篇较旧的帖子时,这里有更多关于模糊图像的更多见解,以便在“imageSmoothingEnabled”解决方案之上进行分层。

这更具体地用于监视器特定渲染的用例,如果他们一直试图将视网膜质量的图形渲染到他们的画布中,结果令人失望,那么只有一些人会遇到这个问题。

从本质上讲,高密度显示器意味着您的画布需要容纳额外的像素密度。如果你什么都不做,你的画布只会将足够的像素信息渲染到它的上下文中,以说明像素比为 1。

因此,对于比率 > 1 的许多现代显示器,您应该更改画布上下文以考虑这些额外信息,但保持画布的正常宽度和高度。

为此,您只需将渲染上下文的宽度和高度设置为:目标宽度和高度 * window.devicePixelRatio。

canvas.width = target width * window.devicePixelRatio;
canvas.height = target height * window.devicePixelRatio;
Run Code Online (Sandbox Code Playgroud)

然后设置画布的样式以按正常尺寸调整画布的大小:

canvas.style.width = `${target width}px`;
canvas.style.height = `${target height}px`;
Run Code Online (Sandbox Code Playgroud)

最后以图像允许的最大上下文大小渲染图像。在某些情况下(例如图像渲染 svg),您仍然可以通过以 pixelRatio 大小的尺寸渲染图像来获得更好的图像质量:

ctx.drawImage(
    img, 0, 0, 
    img.width * window.devicePixelRatio, 
    img.height * window.devicePixelRatio
  );
Run Code Online (Sandbox Code Playgroud)

所以为了炫耀这种现象,我做了一个小提琴。如果您在像素比率接近 1 的显示器上,您将看不到画布质量的差异。

https://jsfiddle.net/ufjm50p9/2/


ale*_*eha 5

除了@canvas 答案。

context.imageSmoothingEnabled = false;
Run Code Online (Sandbox Code Playgroud)

工作完美。但在我的情况下,更改画布的大小将此属性重置为 true。

window.addEventListener('resize', function(e){
    context.imageSmoothingEnabled = false;
}, false)
Run Code Online (Sandbox Code Playgroud)