画布网格在不同的缩放级别变得模糊

时间:2016-08-03 14:40:10

标签: javascript html canvas grid

我正在尝试创建一个简单的画布网格,它将适合玩家当前的缩放级别,但也适合某个画布高度/宽度比例屏幕限制。这是我到目前为止所得到的:

JS:

var bw = window.innerWidth / 2; //canvas size before padding
var bh = window.innerHeight / 1.3; //canvas size before padding
//padding around grid, h and w
var pW = 30;
var pH = 2;
var lLimit = 0; //9 line limit for both height and width to create 8x8

//size of canvas - it will consist the padding around the grid from all sides + the grid itself. it's a total sum
var cw = bw + pW;
var ch = bh + pH;

var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');

var context = canvas.get(0).getContext("2d");

function drawBoard(){ 

     for (var x = 0; lLimit <= 8; x += bw / 8) { //handling the height grid 
        context.moveTo(x, 0);
        context.lineTo(x, bh);
        lLimit++;
    }

    for (var x = 0; lLimit <= 17; x += bh / 8) { //handling the width grid
        context.moveTo(0, x); //begin the line at this cord
        context.lineTo(bw, x); //end the line at this cord
        lLimit++;
    }
    //context.lineWidth = 0.5; what should I put here?
    context.strokeStyle = "black";
    context.stroke();
}

drawBoard(); 

现在,我成功地使画布与每个屏幕分辨率缩放级别处于相同的比例级别。这是我想要实现的目标的一部分。我也尝试实现细线,在所有不同的缩放级别看起来都相同,当然也可以消除模糊。现在的厚度 线条根据缩放级别而变化,有时会模糊不清。

这是jsFiddle(虽然jsFiddle窗口本身很小,所以你几乎没有注意到差异):

https://jsfiddle.net/wL60jo5n/

非常感谢帮助。

3 个答案:

答案 0 :(得分:1)

为防止模糊,您在设置canvas元素的尺寸时应考虑window.devicePixelRatio(当然,在后续绘图中考虑该尺寸)。

width元素的

heightcanvas属性应包含的值与按相同名称的CSS属性中的值成比例。这可以表示为例如如下功能:

function setCanvasSize(canvas, width, height) {
    var ratio = window.devicePixelRatio,
        style = canvas.style;

    style.width  = '' + (width  / ratio) + 'px';
    style.height = '' + (height / ratio) + 'px';

    canvas.width  = width;
    canvas.height = height;
}

答案 1 :(得分:0)

问题是您使用小数值进行绘制。 drawBoard()循环中的画布宽度和位置增量均使用分数。画布是位图表面,而不是矢量绘图。设置画布的宽度和高度时,可以设置存储在内存中的实际像素数。该值不能是十进制(浏览器可能只是修剪小数部分)。当您尝试在小数位置绘制时,画布将使用像素插值来避免锯齿,因此偶尔会出现模糊。

在绘制之前,请参阅我x周围的版本: https://jsfiddle.net/hts7yybm/

在绘制之前尝试舍入值,但不是在实际逻辑中。这样,随着算法不断增加值,不精确度不会叠加。

function drawBoard(){
  for (var x = 0; lLimit <= 8; x += bw / 8) {
    var roundedX = Math.round(x);
    context.moveTo(roundedX, 0);
    context.lineTo(roundedX, bh);
    lLimit++;
  }

  for (var x = 0; lLimit <= 17; x += bh / 8) {
    var roundedX = Math.round(x);
    context.moveTo(0, roundedX);
    context.lineTo(bw, roundedX);
    lLimit++;
  }
  context.lineWidth = 1; // never use decimals
  context.strokeStyle = "black";
  context.stroke();
}

编辑:我非常确定所有浏览器的行为就像画布是img元素一样,因此当用户使用浏览器的缩放功能缩放时,无法防止别名,其他而不是带有前缀的CSS。即使这样,我也不确定浏览器的缩放功能是否考虑到了这一点。

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

另外,请确保画布没有任何CSS设置尺寸。这仅在图像被绘制后拉伸而不是增加绘图表面。如果你想通过赋予100%宽度和高度来填充画布块,那么你需要一些JS来计算CSS给定的高度和宽度,并设置画布的宽度和高度属性的值。那。然后你可以在画布绘图代码中自己实现缩放功能,但是根据你所做的事情,它可能会有点过分。

答案 2 :(得分:0)

为了消除画布缩放/缩放的模糊效果,我在 css 中使用了 image-rendering: pixelated