真正的答案:
-
画布中的每个点的中心在其 (+0.5, +0.5) 坐标中。
因此,为了避免伪影,首先通过 (0.5, 0.5) 翻译上下文,
然后将坐标四舍五入。
-
css 缩放创建工件,只处理画布宽度和高度,除非
你想用 webGL 处理 hidpi 设备,或者以较低的分辨率渲染
同时使用 webGL 和 context2D。
-> 在您的情况下,您的设置代码将是(没有设置 css 宽度/高度):
(http://jsfiddle.net/gamealchemist/x9bTX/8/)
// parameters
var canvasHorizontalRatio = 0.9;
var canvasHeight = 300;
var hCenterCanvas = true;
// setup
var canvasWidth = Math.floor(window.innerWidth * canvasHorizontalRatio);
var cnv = document.getElementById("myCanvas");
cnv.width = canvasWidth;
cnv.height = canvasHeight;
if (hCenterCanvas)
cnv.style['margin-left'] = Math.floor((window.innerWidth - canvasWidth) * 0.5) + 'px';
var ctx = cnv.getContext("2d");
ctx.translate(0.5, 0.5);
gridContext();
其余代码与您的原始代码相同,我只是更改了正方形的大小以获得完全相同的视觉效果。
ctx.beginPath();
for (var i=60; i<canvasHeight; i+=60) {
ctx.moveTo(0,i);
ctx.lineTo(canvasWidth,i);
}
for (i=60; i<canvasWidth; i+=60) {
ctx.moveTo(i,0);
ctx.lineTo(i,canvasHeight);
}
ctx.strokeStyle="#000";
ctx.stroke();
ctx.closePath();
随着这些变化,我们开始:
到:
编辑:为了确保四舍五入,实际上我认为最方便的是注入上下文并更改 moveTo、lineTo :
function gridContext() {
var oldMoveTo = CanvasRenderingContext2D.prototype.moveTo;
CanvasRenderingContext2D.prototype.moveTo = function (x,y) {
x |= 0; y |= 0;
oldMoveTo.call(this, x, y);
}
var oldLineTo = CanvasRenderingContext2D.prototype.lineTo;
CanvasRenderingContext2D.prototype.lineTo = function (x,y) {
x |= 0; y |= 0;
oldLineTo.call(this, x, y);
}
}
显然,您必须为所需的所有绘图功能执行此操作。