CanvasRenderingContext2D.strokeRect仍尝试对我的值进行抗锯齿,而不是绘制一个像素 [英] CanvasRenderingContext2D.strokeRect still tries to antialias my values, instead of drawing one pixel

查看:123
本文介绍了CanvasRenderingContext2D.strokeRect仍尝试对我的值进行抗锯齿,而不是绘制一个像素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作图表,主要是作为练习.该图尝试通过线连接值,但是如果无法连接值,则仅绘制一个像素.

在下面的示例中,我确保minYmaxYpixelX都是整数值.它们实际上来自我真实代码中的Int32Array.

        // some min max range for this X pixel coordinate
        const minY = data[i].min;
        const maxY = data[i].max;
        // if there are multiple values on this X coordinate
        if (maxY - minY > 1) {
            ctx.beginPath();
            ctx.moveTo(pixelX + 0.5, minY + 0.5);
            ctx.lineTo(pixelX + 0.5, maxY + 0.5);
            ctx.closePath();
            ctx.stroke();
        }
        // otherwise just draw a pixel
        else {
            // if the value was interpolated, it's already colored for this pixel
            if (!valueIsInterpolated) {
                ctx.strokeRect(pixelX + 0.5, minY + 0.5, 1, 1);
            }
        }

其中应绘制单个像素,但应绘制各种形状的矩形,这些矩形在图形中看起来非常难看.

如果我从通话中删除+ 0.5,它会看起来像这样:

那更糟.如何确保strokeRect精确绘制一个像素?没有有趣的事情,没有抗锯齿.只需标记一个像素即可.为什么会这样?

解决方案

您正在使用strokeRect(),它将绘制1像素矩形的轮廓,这意味着您将得到一半各个方向上的外部像素(假设线的宽度为1像素),则需要进行抗锯齿处理.

您想使用fillRect()代替,它将填充 1个像素区域.

 const ctx = c.getContext("2d");
for(let x = 5; x < c.width; x += 10) ctx.fillRect(x, 5, 1, 1); 

 <canvas id=c></canvas> 

与使用strokeRect()相比,它将从向量框的所有方向(您不希望的)渗出" 0.5(线宽= 1):

 const ctx = c.getContext("2d");
for(let x = 5; x < c.width; x += 10) ctx.strokeRect(x, 5, 1, 1); 

 <canvas id=c></canvas> 

I'm making a graph, mostly as an exercise. The graph tries to connect values by lines, but if a value cannot be connected, it just draws a pixel.

In the following example, I made sure that minY, maxY and pixelX are all integer values. They actually come from Int32Array in my real code.

        // some min max range for this X pixel coordinate
        const minY = data[i].min;
        const maxY = data[i].max;
        // if there are multiple values on this X coordinate
        if (maxY - minY > 1) {
            ctx.beginPath();
            ctx.moveTo(pixelX + 0.5, minY + 0.5);
            ctx.lineTo(pixelX + 0.5, maxY + 0.5);
            ctx.closePath();
            ctx.stroke();
        }
        // otherwise just draw a pixel
        else {
            // if the value was interpolated, it's already colored for this pixel
            if (!valueIsInterpolated) {
                ctx.strokeRect(pixelX + 0.5, minY + 0.5, 1, 1);
            }
        }

Of it SHOULD draw a single pixel, but instead, it draws variously shaped rectangles which look REALLY ugly in the graph.

It would look like this if I remove the + 0.5 from the call:

That's even worse. How can I make sure that strokeRect draws EXACTLY ONE pixel? No funny business, no anti-aliasing. Just mark a pixel. Why is this happening?

解决方案

You're using strokeRect() which will draw an outline of your 1-pixel rectangle meaning you will end up with a half pixel outside in all directions (assuming 1 pixel width of the line) which will need to be anti-aliased.

You'd want to use fillRect() instead which will fill that 1 pixel area.

const ctx = c.getContext("2d");
for(let x = 5; x < c.width; x += 10) ctx.fillRect(x, 5, 1, 1);

<canvas id=c></canvas>

Compared to using strokeRect() which will "bleed" 0.5 (with line width = 1) in all directions from the vector box (which you don't want):

const ctx = c.getContext("2d");
for(let x = 5; x < c.width; x += 10) ctx.strokeRect(x, 5, 1, 1);

<canvas id=c></canvas>

这篇关于CanvasRenderingContext2D.strokeRect仍尝试对我的值进行抗锯齿,而不是绘制一个像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆