简体   繁体   English

帆布/精确线条画

[英]Canvas / precise line drawing

I'm playing currently with javascript and canvas around. 我现在正在玩javascript和canvas。

I want draw a 1 pixel border without blurry lines. 我想画一个没有模糊线条的1像素边框。 I've read about the 0.5 px translation. 我读过有关0.5 px的翻译。

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

What is wrong ? 怎么了 ? JSFiddle 的jsfiddle

Why is one pixel missing in the right bottom corner ? 为什么右下角会丢失一个像素?

This works!! 这个有效!!

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);
};

The issue with your attempt was that a pixel too close to the edge could be shifted "off" the canvas. 您尝试的问题是太靠近边缘的像素可能会从画布“移开”。 This method ensures that if the point is within 2 pixels of an edge, the shifting occurs in a direction AWAY from the edge. 该方法确保如果该点在边缘的2个像素内,则移位发生在距边缘的AWAY方向上。

The center of a screen pixel is it at its (+0.5,+0.5) context2d coordinate. 屏幕像素的中心是它的(+ 0.5,+ 0.5)context2d坐标。

Truth is you don't have to translate by 0.5 for x OR y, but for both , be it a vertical or horizontal line. 事实是你不必为x OR y翻译0.5,但对于两者 ,无论是垂直线还是水平线。

Your whole code is equivalent to this one : 您的整个代码与此相同:

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.

It's easy to see that points do not connect one to another. 很容易看出点不会相互连接。 There are 8 points involved here, not 4. 这里涉及8点,而不是4点。
The right-down most point (399.5, 399.5) is never reached, while other corners have at least 2 points drawn. 永远不会达到右下角的最高点(399.5,399.5),而其他角落至少有2个点。

A simple way to settle the issue once and for all is to translate the canvas by (0.5, 0.5) on context creation, and use rounded coordinates after that. 一劳永逸地解决问题的一种简单方法是在创建上下文时将画布转换为(0.5,0.5),然后使用舍入坐标。
Obviously -as it should always be done- save/restore the context when using a transform. 显然 - 它应该始终完成 - 使用转换时保存/恢复上下文。

http://jsfiddle.net/gamealchemist/xaxK4/6/ http://jsfiddle.net/gamealchemist/xaxK4/6/

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);

And do not use css width/height, or maybe set it in the code to ensure you never have canvas.width != canvas.style.width or canvas.height != canvas.style.height, unless you know what you're doing in having different values of course. 并且不要使用css宽度/高度,或者可以在代码中设置它以确保你永远不会有canvas.width!= canvas.style.width或canvas.height!= canvas.style.height,除非你知道你是什么当然,做不同的价值观。 But if you don't plan on playing with resolution, to support hiDpi devices, or to render at a lower resolution, quit using css sizing. 但是,如果您不打算使用分辨率,支持hiDpi设备或以较低分辨率渲染,请使用css大小调整退出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM