Javascript 画布/精确线条绘制

Javascript 画布/精确线条绘制,javascript,Javascript,我现在正在玩javascript和画布 我想画一个没有模糊线条的1像素边框。 我读过关于0.5像素的翻译 var shift = 0.5; if (x1 === x2) { var shiftX = shift; var shiftY = 0; } else { var shiftX = 0; var shiftY = shift; } 怎么了 为什么右下角少了一个像素?这很有效 ctx.line = function (x1, y1, x2, y2) { var sh

我现在正在玩javascript和画布

我想画一个没有模糊线条的1像素边框。 我读过关于0.5像素的翻译

var shift = 0.5;
if (x1 === x2) {
  var shiftX = shift;
  var shiftY = 0;
} else {
  var shiftX = 0;
  var shiftY = shift;
}
怎么了

为什么右下角少了一个像素?

这很有效

ctx.line = function (x1, y1, x2, y2) {
    var shift = 0.5;

    if (x1 === x2) {
        var shiftX = x1 < 2 ? shift : -shift;
        var shiftY = 0;
    } else if (y1 === y2) {
        var shiftX = 0;
        var shiftY = y1 < 2 ? shift : -shift;
    } else {
        var shiftX = 0;
        var shiftY = 0;
    }

    ctx.translate(shiftX, shiftY);
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.stroke();
    ctx.translate(-shiftX, -shiftY);
};
ctx.line=函数(x1,y1,x2,y2){
var偏移=0.5;
如果(x1==x2){
var shiftX=x1<2?移位:-移位;
var-shiftY=0;
}else if(y1==y2){
var-shiftX=0;
var移位=y1<2?移位:-移位;
}否则{
var-shiftX=0;
var-shiftY=0;
}
ctx.translate(shiftX,shiftY);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.stroke();
ctx.translate(-shiftX,-shiftY);
};

您尝试的问题是,过于靠近边缘的像素可能会“移出”画布。此方法可确保如果点位于边缘的2个像素范围内,则移动发生在远离边缘的方向上。

屏幕像素的中心位于其(+0.5,+0.5)上下文2D坐标处

事实上,对于x或y,不必平移0.5,但对于这两种情况,无论是垂直线还是水平线

您的整个代码与此代码等效:

ctx.sline(0    , 0.5,      399,   0.5);
ctx.sline(399.5 ,0,        399.5, 399);
ctx.sline(0     ,399.5,    399,   399.5);
ctx.sline(0.5   ,399,      0.5,   0);
// With 'sline' a straight line function that just use provided coordinates.
很容易看出点之间没有连接。这里涉及8点,而不是4点。
永远不会到达最右下角点(399.5399.5),而其他角点至少绘制了2个点

一个一劳永逸解决问题的简单方法是在创建上下文时将画布平移(0.5,0.5),然后使用四舍五入坐标。
显然,在使用转换时,应该始终保存/恢复上下文


不要使用css宽度/高度,或者在代码中设置它以确保您永远不会使用canvas.width!=canvas.style.width或canvas.height!=canvas.style.height,当然,除非你知道你在拥有不同的价值观方面做了什么。但是,如果您不打算使用分辨率、支持hiDpi设备或以较低的分辨率渲染,请停止使用css大小调整。

使用
var shift=-.5不确定原因,但这修复了
ctx.line(400,1400,401)长一个像素。@Zachsauier,比你失去左上角的部分还长@gongzhitaao-丑陋的黑客,这就是为什么我问原因,我想了解原因,但谢谢。尝试删除赋予画布宽度和高度的css样式。在对html画布图形有了相当多的经验之后,我注意到,如果你用css设计画布的宽度/高度,画布会变得非常糟糕-总是使用内联属性。不要更改shift值-它不是要更改的!移位取决于线宽:var shift=(线宽%2)/2;我承认在编码时没有考虑线宽。我会给这个答案一个快速编辑。移位不取决于线宽。在地板上筛一筛(线宽/2)将刚好位于它的正/底部中心。想象一下像素的网格:只有0.5的移位才有意义,比如说3.5的移位与0.5像素的情况相同,只有3个像素在下面。
ctx.translate(0.5, 0.5);
ctx.lineWidth = 1;
ctx.strokeStyle = "#AAAAAA";

ctx.line = function (x1, y1, x2, y2) {
    x1 = 0 | x1 ;
    y1 = 0 | y1 ;
    x2 = 0 | x2 ;
    y2 = 0 | y2 ;
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.stroke();
};

ctx.line(1, 1, 399, 1);
ctx.line(399, 1, 399, 399);
ctx.line(399, 399, 1, 399);
ctx.line(1, 399, 1, 1);