使用画布缩放图像而不会使其模糊

时间:2014-04-24 13:58:15

标签: javascript html5 canvas html5-canvas

我有一个名为Engine.Renderer的班级。它只是创建一个新的画布,让我可以轻松更新和渲染活动画布'现场。创建新画布时,我将这些设置应用于其上下文:

this.context.imageSmoothingEnabled       = false;
this.context.mozImageSmoothingEnabled    = false;
this.context.webkitImageSmoothingEnabled = false;

在CSS中,我添加了这些内容:

main canvas {
    position: absolute;
    top: 0;

    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor
}

我还编写了一个将画布调整到窗口的函数:

[...]
resize: function () {
    var width  = window.innerWidth;
    var height = width / 16 * 9;

    if ( height > window.innerHeight ) {
        height = window.innerHeight;
        width  = height * 16 / 9;
    }

    if ( width > window.innerWidth ) {
        width  = window.innerWidth;
        height = width / 16 * 9;
    }

    width  = Number( width ).toFixed();
    height = Number( height ).toFixed();

    this.canvas.style.width  = width  + "px";
    this.canvas.style.height = height + "px";

    this.container.style.width  = width  + "px";
    this.container.style.height = height + "px";
    this.container.style.left   = ( ( window.innerWidth - width ) / 2 ) + "px";

    // the new scale
    this.scale = ( width / this.canvas.width ).toFixed( 2 );
}
[...]

现在,我有一个名为Character的类。该类能够在给定画布上创建和呈现新角色。渲染部分如下所示:

context.drawImage(
    this.outfit,

    this.sprite    * this.dimension.width,
    this.direction * this.dimension.height,

    this.dimension.width,
    this.dimension.height,

    this.position.x,
    this.position.y,

    // set the character sizes to normal size * scale
    this.dimension.width  * this.renderer.scale,
    this.dimension.height * this.renderer.scale
);

我有两个问题:

  1. 游戏性能比以前更差(在~1400x800px画布上渲染单个角色时约为9 FPS);
  2. 字符'图像并没有像以前那么模糊,但我仍然可以看到一点模糊;
  3. 我该如何解决这些问题?

1 个答案:

答案 0 :(得分:1)

尝试对位置和大小使用整数值:

context.drawImage(
    this.outfit,

    this.sprite    * this.dimension.width,
    this.direction * this.dimension.height,

    this.dimension.width,
    this.dimension.height,

    this.position.x|0,          // make these integer
    this.position.y|0,

    // set the character sizes to normal size * scale
    (this.dimension.width  * this.renderer.scale)|0,
    (this.dimension.height * this.renderer.scale)|0
);

另外,使用CSS /样式设置画布大小会影响插值。根据我自己的测试,插值的CSS设置似乎不再影响画布内容。

最好是,如果你需要一个固定的小尺寸放大,正确设置画布大小,而是使用缩放变换(或缩放值)来绘制内容:

this.canvas.width  = width;
this.canvas.height = height;

更新:根据评论 -

更改画布元素的大小时,状态也会重置,这意味着需要重新应用图像平滑设置。

当禁用图像平滑时,浏览器将使用最近邻居,这意味着在缩放2 ^ n(2x,4x,8x或0.5x,0.25x等)或“clunkyness”可能显示时获得最佳结果。< / p>

modified fiddle here