缩放 <canvas> 时禁用插值 [英] Disable Interpolation when Scaling a <canvas>

查看:22
本文介绍了缩放 <canvas> 时禁用插值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这与现有画布元素在放大时的呈现方式有关不是处理线条或图形如何渲染到画布表面.换句话说,这与缩放元素插值有关,而与在画布上绘制的图形的抗锯齿无关.我不关心浏览器如何画线;我关心浏览器在放大时如何呈现画布元素本身.

<小时>

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

应该做我想要的:

<块引用>

图像渲染属性向用户代理提供了关于在缩放图像时保留图像的哪些方面最重要的提示,以帮助用户代理选择合适的缩放算法.

>

规范概述了三个可接受的值:autocrisp-edgespixelated.

<块引用>

像素化:

放大图像时,必须使用最近邻"或类似算法,使图像看起来只是由非常大的像素组成.缩小时,这与自动相同.

标准?跨浏览器?

由于这只是一个工作草案,不能保证这会成为标准.浏览器支持目前充其量只是参差不齐.

Mozilla 开发者网络有

NOTE: This has to do with how existing canvas elements are rendered when scaled up, not to do with how lines or graphics are rendered onto a canvas surface. In other words, this has everything to do with interpolation of scaled elements, and nothing to do with antialiasing of graphics being drawn on a canvas. I'm not concerned with how the browser draws lines; I care about how the browser renders the canvas element itself when it is scaled up.


Is there a canvas property or browser setting I can change programmatically to disable interpolation when scaling <canvas> elements? A cross-browser solution is ideal but not essential; Webkit-based browsers are my main target. Performance is very important.

This question is most similar but does not illustrate the problem sufficiently. For what it's worth, I have tried image-rendering: -webkit-optimize-contrast to no avail.

The application will be a "retro" 8-bit styled game written in HTML5+JS to make it clear what I need.


To illustrate, here is an example. (live version)

Suppose I have a 21x21 canvas...

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

...which has css that makes the element 5 times larger (105x105):

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

I draw a simple 'X' on the canvas like so:

$('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();
});

The image on the left is what Chromium (14.0) renders. The image on the right is what I want (hand-drawn for illustrative purposes).

解决方案

Last Updated: 2014-09-12

Is there a canvas property or browser setting I can change programmatically to disable interpolation when scaling elements?

The answer is maybe some day. For now, you'll have to resort to hack-arounds to get what you want.


image-rendering

The working draft of CSS3 outlines a new property, image-rendering that should do what I want:

The image-rendering property provides a hint to the user-agent about what aspects of an image are most important to preserve when the image is scaled, to aid the user-agent in the choice of an appropriate scaling algorithm.

The specification outlines three accepted values: auto, crisp-edges, and pixelated.

pixelated:

When scaling the image up, the "nearest neighbor" or similar algorithm must be used, so that the image appears to be simply composed of very large pixels. When scaling down, this is the same as auto.

Standard? Cross-browser?

Since this is merely a working draft, there's no guarantee that this will become standard. Browser support is currently spotty, at best.

The Mozilla Developer Network has a pretty thorough page dedicated to the current state of the art which I highly recommend reading.

The Webkit developers initially chose to tentatively implement this as -webkit-optimize-contrast, but Chromium/Chrome don't seem to be using a version of Webkit that implements this.

Update: 2014-09-12

Chrome 38 now supports image-rendering: pixelated!

Firefox has a bug report open to get image-rendering: pixelated implemented, but -moz-crisp-edges works for now.

Solution?

The most cross-platform, CSS-only solution so far is thus:

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                            */
}

Sadly this wont work on all major HTML5 platforms yet (Chrome, in particular).

Of course, one could manually scale up images using nearest-neighbor interpolation onto high-resolution canvas surfaces in javascript, or even pre-scale images server-side, but in my case this will be forbiddingly costly so it is not a viable option.

ImpactJS uses a texture pre-scaling technique to get around all this FUD. Impact's developer, Dominic Szablewski, wrote a very in-depth article about this (he even ended up citing this question in his research).

See Simon's answer for a canvas-based solution that relies on the imageSmoothingEnabled property (not available in older browsers, but simpler than pre-scaling and pretty widely-supported).

Live Demo

If you'd like to test the CSS properties discussed in the MDN article on canvas elements, I've made this fiddle which should display something like this, blurry or not, depending on your browser:

这篇关于缩放 &lt;canvas&gt; 时禁用插值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆