我正在尝试创建一个简单的画布网格,它将适合玩家当前的缩放级别,但也适合一定的画布高度/宽度比例屏幕限制。这是我到目前为止得到的:
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/
我们将非常感谢您的帮助。
如果你想消除画布缩放/缩放时的像素模糊,可以使用
image-rendering: pixelated
CSS 属性
为了防止模糊,您应该在设置 window.devicePixelRatio
元素的尺寸时考虑
canvas
(当然,并在后续绘制过程中考虑该尺寸)。
width
和 height
元素的 canvas
属性所包含的值应按比例高于同名 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;
}
问题是您正在使用十进制值来绘图。画布宽度和
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 给定的高度和宽度,并根据该值设置画布的宽度和高度属性的值。然后,您可以在画布绘图代码中实现自己的缩放功能,但根据您正在执行的操作,这可能有点过头了。