2016-08-03 106 views
0

我想创建一个简单的画布网格,它将适合玩家的当前缩放级别,但也适用于某个画布高度/宽度成比例的屏幕限制。以下是我走到这一步:画布网格在不同的缩放级别变得模糊

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/

帮助将不胜感激。

+0

当你说缩放级别,你的意思是缩放内置到大多数浏览器(使用控制+ mwheel上/下)? –

+0

是的。 window.innerWidth会在页面加载时考虑用户的当前缩放级别。 – RunningFromShia

+0

我尝试实现的网格系统的实例:http://slither.io/无论您进入网页的缩放级别如何,或者即使在游戏过程中放大和缩小,网格系统看起来都一样。 – RunningFromShia

回答

0

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

看到一个版本,我之前绘制圆xhttps://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给定的高度和宽度,并基于此设置画布宽度和高度属性的值。然后,您可以在画布绘图代码中自行实现缩放功能,但根据您所做的操作,这可能是矫枉过正的。

+0

我应用了你所做的,但没有奏效。将缩放级别放在200%以上,然后刷新页面。然后把它放在300%并刷新。您会注意到每个缩放级别的变化;它变得更厚或更薄。测试应该在普通的HTML窗口上执行,而不是jsFiddle,因为差异不明显。 – RunningFromShia

+0

我用新的信息编辑了答案。 –

0

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

widthheightcanvas元素的属性应该包含比例高于相同名称的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; 
}