我在 HMTL 5 2D Canvas 上绘制了 5 条水平线:
var canvas_ctx = my_canvas.getContext("2d");
canvas_ctx.lineWidth = 0.5;
canvas_ctx.strokeStyle = "black";
{
let line_x = 0;
let line_length = canvas_ctx.width;
let offset = 5;
let numLines = 5;
let numYincrement = 10;
for (let i=0;i<numLines * numYincrement;i+=numYincrement) {
//canvas_ctx.beginPath();
canvas_ctx.moveTo(line_x,i + offset);
canvas_ctx.lineTo(line_length,i + offset);
canvas_ctx.stroke();
//canvas_ctx.closePath();
}
}
理想情况下,这应该会产生 5 条黑线。相反,线条的颜色似乎随着每条新线而逐渐消失(好像是渐变!),因此第 5 行是灰色的。如果我取消注释 canvas_ctx.beginPath();
和 canvas_ctx.closePath();
,所有行都会变成灰色。为什么会这样??
最佳答案
笔划确实从坐标的两侧重叠。
var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// draw big
ctx.scale(30, 30);
ctx.beginPath();
ctx.moveTo(5, 0);
ctx.lineTo(5, 10);
ctx.stroke();
drawPixelGrid();
function drawPixelGrid() {
// simply renders where the pixel bounds are
ctx.beginPath();
// remove the zoom
ctx.setTransform(1,0,0,1,0,0);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 2; // avoid the problem we are demonstrating by using a perfect lineWidth ;-)
for(let y=0; y<=300; y+=30) {
ctx.moveTo(0, y);
ctx.lineTo(300, y);
for(let x=0; x<=300; x+=30) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 300);
}
}
ctx.stroke();
}
<canvas id="c" height=300></canvas>
但显然,一个像素不能同时设置为两种颜色。所以浏览器适用antialiasing ,这会将您的像素颜色淡化为另一种颜色,这是混合背景和前景色的结果。 因此,对于白色或透明背景上的黑色描边,这会导致渲染实际的灰色像素。这里我将继续以红色为例:
var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// first draw as on a 10*10 canvas
ctx.beginPath();
ctx.moveTo(5, 0);
ctx.lineTo(5, 10);
ctx.stroke();
// zoom it
ctx.imageSmoothingEnabled = 0;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(c, 0,0,9000,9000);
drawPixelGrid();
// this is not red...
function drawPixelGrid() {
ctx.globalCompositeOperation = 'source-over';
ctx.beginPath();
ctx.setTransform(1,0,0,1,0,0);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 2;
for(let y=0; y<=300; y+=30) {
ctx.moveTo(0, y);
ctx.lineTo(300, y);
for(let x=0; x<=300; x+=30) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 300);
}
}
ctx.stroke();
}
<canvas id="c" height=300></canvas>
避免它的一种方法通常是在您的坐标上应用偏移量,以便该线在像素边界上正确延伸。例如,对于 1px 的线宽,您将应用 0.5 的偏移量:
var ctx = c.getContext('2d');
ctx.strokeStyle="red";
// first draw as on a 10*10 canvas
ctx.beginPath();
ctx.moveTo(5.5, 0); // offset +0.5px
ctx.lineTo(5.5, 10);
ctx.stroke();
// zoom it
ctx.imageSmoothingEnabled = 0;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(c, 0,0,9000,9000);
drawPixelGrid();
// now we've got a real red
function drawPixelGrid() {
ctx.globalCompositeOperation = 'source-over';
ctx.beginPath();
ctx.setTransform(1,0,0,1,0,0);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 2;
for(let y=0; y<=300; y+=30) {
ctx.moveTo(0, y);
ctx.lineTo(300, y);
for(let x=0; x<=300; x+=30) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 300);
}
}
ctx.stroke();
}
<canvas id="c" height=300></canvas>
但在您的情况下,您以 0.5 像素的线宽绘制,因此没有偏移量能够消除这种抗锯齿。
因此,如果您想要完美的颜色,请选择正确的线宽。
关于javascript - html 5 canvas LineTo() 线条颜色问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49733682/