使用for循环在画布上绘制直线

7

我正在尝试使用canvas绘制线条,并使用for循环更改坐标。

这是我的canvas元素:

<canvas id="c" width="300px" height="300px"></canvas>

这里是 JavaScript 代码:

var c = document.getElementById('c');
ci = c.getContext('2d');
for(var a = 18; a < 300; a +=18){
            fnc(a, ci);
            }   
function fnc(x, ci){

        ci.strokeStyle = 'red'; 
        ci.moveTo(0, x); 
        ci.lineTo(300, x); ci.lineWidth = 0.2; ci.stroke(); 
    }

您可以看到,我正在尝试在这些线之间使用18像素的间隔进行绘制。但是,线条的粗细和颜色(或不透明度,我不确定)从上到下发生了变化。

这里是一个示例:http://jsfiddle.net/J6zzD/1/

所以,我找不到错误在哪里。为什么颜色和厚度不同呢?

更新:

我将这些行代码写在函数外面,现在所有的线条都变得模糊了,但是它们的厚度是一样的。太奇怪了:

 ci.strokeStyle = 'red'; 
 ci.lineWidth = 0.2; ci.stroke();

这里有一个演示:http://jsfiddle.net/J6zzD/4/

2个回答

6
这又是忘记调用beginPath的永恒问题。
每次调用moveTo和lineTo时,都会创建一个新的*子路径*,它将添加到当前路径中。
然后,每次调用stroke()时,都会绘制当前路径,因此在第一次绘制最后添加的路径时,所有当前子路径都会重新绘制。
由于不透明度会累加,当只绘制一次底部线条(lineWidth=0.2)时,顶部线条将达到100%的不透明度(alpha=255)。

在您的第二个fiddle中,您只绘制了一次,因此所有线条的不透明度都为20%,这对于0.2 lineWidth是正确的。

所以:在绘制新图形之前使用beginPath。
在这种情况下,您有两个选择:
• 逐行绘制 OR
• 一次绘制包含所有线条的路径。

(请参见下面的代码)。

TIP:为了获得清晰的线条,请记住像素的中心位于每个像素的(+0.5,+0.5)坐标处,因此“技巧”是在应用程序启动时平移0.5、0.5,然后仅使用舍入的坐标和lineWidth

1)逐行绘制

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

var c = document.getElementById('c');
var ctx = c.getContext('2d');
ctx.translate(0.5, 0.5);
ctx.lineWidth = 1;

for (var y = 18; y < 300; y += 18) {
    strokeLine(ctx, y);
}

function strokeLine(ctx, y) {
    ctx.beginPath();
    ctx.strokeStyle = 'red';
    ctx.moveTo(0, y);
    ctx.lineTo(300, y);
    ctx.stroke();
}

2) 绘制多个子路径: (每个stroke()只能有一种颜色)

http://jsfiddle.net/gamealchemist/J6zzD/7/

var c = document.getElementById('c');
var ctx = c.getContext('2d');
ctx.translate(0.5, 0.5);
ctx.lineWidth = 1;

ctx.strokeStyle = 'red';

ctx.beginPath();
for (var y = 18; y < 300; y += 18) {
    addLineSubPath(ctx, y);
}
ctx.stroke();

function addLineSubPath(ctx, y) {
    ctx.moveTo(0, y);
    ctx.lineTo(300, y);
}

4
请看:https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example 由于画布坐标不直接参考像素,必须特别小心地获得清晰的水平和垂直线条。
基本上,因为您尝试绘制宽度为0.2像素的线条,所以浏览器会进行一些数学运算,将连续数字近似为离散单位,从而产生“褪色”线条。
现在我们可以通过将 context.lineWidth 更改为1(我实际上删除它,因为它默认为1)并将所有内容向下移动半个像素来修复您的代码。
var c = document.getElementById('c');
ci = c.getContext('2d');
for(var a = 18.5; a < 300.5; a +=18)
{
    fnc(a, ci);
}   

function fnc(x, ci)
{
    ci.strokeStyle = 'red'; 
    ci.moveTo(0, x); 
    ci.lineTo(300, x);
    ci.stroke();
}

Demo


谢谢您的好回答。我也更新了我的问题。那么在我的情况下没有办法画出0.2px的线吗?:/ - ctarimli
2
0.2像素宽的线条会是什么样子? - Meredith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接