缩放<canvas> </canvas>时禁用插值

时间:2011-09-30 19:14:48

标签: javascript html5 canvas

注意 :这与现有画布元素在按比例放大时的呈现方式有关如何将线条或图形渲染到画布表面。换句话说,这与缩放元素 interpolation 有关,而与在画布上绘制的图形的 antialiasing 无关。我不关心浏览器如何绘制线条;我关心浏览器在放大时如何呈现canvas元素本身


是否有画布属性或浏览器设置我可以通过编程方式更改以在缩放<canvas>元素时禁用插值?跨浏览器解决方案是理想的,但不是必需的;基于Webkit的浏览器是我的主要目标。表现非常重要。

This question最相似,但没有充分说明问题。对于它的价值,我试过image-rendering: -webkit-optimize-contrast无济于事。

该应用程序将是一个用HTML5 + JS编写的“复古”8位风格游戏,以明确我需要的内容。


为了说明,这是一个例子。 (live version

假设我有一个21x21画布......

<canvas id='b' width='21' height='21'></canvas>

...有css使元素大5倍(105x105):

canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */

我在画布上画了一个简单的'X',如下:

$('canvas').each(function () {
    var ctx = this.getContext("2d");
    ctx.moveTo(0,0);
    ctx.lineTo(21,21);
    ctx.moveTo(0,21);
    ctx.lineTo(21,0);
    ctx.stroke();
});

左边的图像是Chromium(14.0)渲染的图像。右边的图像是我想要的(手绘为了说明目的)。

Chrome interpolates scaled canvas elements A non-interpolated version

5 个答案:

答案 0 :(得分:116)

最后更新时间:2014-09-12

  

是否有画布属性或浏览器设置我可以通过编程方式更改以在缩放元素时禁用插值?

答案是可能有一天。现在,你将不得不诉诸黑客来获得你想要的东西。


image-rendering

The working draft of CSS3 outlines a new property, image-rendering应该做我想做的事:

  

图像呈现属性向用户代理提供有关在缩放图像时图像的哪些方面最重要的提示,以帮助用户代理选择适当的缩放算法。

规范概述了三个可接受的值:autocrisp-edges pixelated

  

<强>像素化

     

向上缩放图像时,必须使用“最近邻居”或类似算法,以使图像看起来简单地由非常大的像素组成。按比例缩小时,这与auto相同。

标准?跨浏览器?

由于这仅仅是工作草案,因此无法保证这将成为标准。浏览器支持目前很不稳定。

Mozilla开发者网络有a pretty thorough page dedicated to the current state of the art我强烈建议您阅读。

Webkit开发人员最初选择tentatively implement this as -webkit-optimize-contrast,但Chromium / Chrome似乎没有使用实现此功能的Webkit版本。

更新时间:2014-09-12

Chrome 38 now supports image-rendering: pixelated

Firefox已开放bug report以实现image-rendering: pixelated,但-moz-crisp-edges暂时有效。

解?

到目前为止,最具跨平台性,仅限CSS的解决方案是:

canvas {
  image-rendering: optimizeSpeed;             /* Older versions of FF          */
  image-rendering: -moz-crisp-edges;          /* FF 6.0+                       */
  image-rendering: -webkit-optimize-contrast; /* Safari                        */
  image-rendering: -o-crisp-edges;            /* OS X & Windows Opera (12.02+) */
  image-rendering: pixelated;                 /* Awesome future-browsers       */
  -ms-interpolation-mode: nearest-neighbor;   /* IE                            */
}

可悲的是,这还不适用于所有主要的HTML5平台(特别是Chrome)。

当然,人们可以使用最近邻插值手动将图像放大到javascript中的高分辨率画布表面,甚至是服务器端的预缩放图像,但在我的情况下,这将是非常昂贵的,因此它不是可行的选择。

ImpactJS使用纹理预缩放技术来绕过所有这些FUD。 Impact的开发人员,Dominic Szablewski,wrote a very in-depth article about this(他甚至在他的研究中引用了这个问题)。

请参阅Simon's answer,了解依赖于imageSmoothingEnabled属性的基于画布的解决方案(在旧版浏览器中不可用,但比预缩放更简单且得到广泛支持)。

现场演示

如果您想测试关于canvas元素的MDN文章中讨论的CSS属性,我已经this fiddle应该显示类似的内容,模糊与否,具体取决于您的浏览器: a 4:1 (64x64 to 256x256) image of an isometric pixel-art style TV

答案 1 :(得分:58)

新答案7/31/2012

这终于在画布规范中了!

该规范最近添加了一个名为imageSmoothingEnabled的属性,默认为true,并确定在非整数坐标上绘制或绘制缩放的图像是否将使用更平滑的算法。如果设置为false则使用最近邻居,从而产生不太平滑的图像,而只是制作更大的像素。

图像平滑最近才被添加到画布规范中,并不是所有浏览器都支持,但是某些浏览器已经实现了此属性的供应商前缀版本。在上下文中,Firefox中存在mozImageSmoothingEnabled,Chrome和Safari中存在webkitImageSmoothingEnabled,并且将这些设置为false将停止发生反锯齿。不幸的是,在撰写本文时,IE9和Opera尚未实现此属性,供应商前缀或其他。


预览: JSFiddle

结果:

enter image description here

答案 2 :(得分:11)

编辑7/31/2012 - 此功能现在在画布规范中!请点击此处单独的答案:

https://stackoverflow.com/a/11751817/154112

以下是对后代的回答。


根据您所需的效果,您可以将其作为一个选项:

var can = document.getElementById('b');
var ctx = can.getContext('2d');
ctx.scale(5,5);
$('canvas').each(function () {
    var ctx = this.getContext("2d");
    ctx.moveTo(0,0);
    ctx.lineTo(21,21);
    ctx.moveTo(0,21);
    ctx.lineTo(21,0);
    ctx.stroke();
});

http://jsfiddle.net/wa95p/

创造了这个:

enter image description here

可能不是你想要的。但是,如果你只是想要零模糊那么这将是票,所以我会提供它以防万一。

更困难的选择是使用像素操作并自己编写算法来完成工作。第一图像的每个像素在新图像上变为5×5像素块。使用imagedata并不难。

但Canvas和CSS本身并没有帮助你将这一点扩展到另一个具有你想要的确切效果。

答案 3 :(得分:4)

在Google Chrome中,不会插入画布图像模式。

以下是根据namuol答案http://jsfiddle.net/pGs4f/

编辑的工作示例
ctx.scale(4, 4);
ctx.fillStyle = ctx.createPattern(image, 'repeat');
ctx.fillRect(0, 0, 64, 64);

答案 4 :(得分:1)

Saviski's workaround已明确here很有希望,因为它适用于:

  • Chrome 22.0.1229.79 Mac OS X 10.6.8
  • Chrome 22.0.1229.79 m Windows 7
  • Chromium 18.0.1025.168(Developer Build 134367 Linux)Ubuntu 11.10
  • Firefox 3.6.25 Windows 7

但不适用于以下内容,但使用CSS图像渲染可以实现相同的效果:

  • Firefox 15.0.1 Mac OS X 10.6.8(图像渲染:-moz-crisp-edges适用于this
  • Opera 12.02 Mac OS X 10.6.8(图像渲染:-o-crisp-edges适用于this
  • Opera 12.02 Windows 7(图像渲染:-o-crisp-edges适用于this

问题是这些,因为ctx.XXXImageSmoothingEnabled不起作用且图像渲染不起作用:

  • Safari 5.1.7 Mac OS X 10.6.8。 (图像渲染:-webkit-optimize-contrast NOT工作)
  • Safari 5.1.7 Windows 7(图像渲染:-webkit-optimize-contrast NOT无效)
  • IE 9 Windows 7(-ms-interpolation-mode:nearest-neighbor NOT工作)