问题
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?
回答1:
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>
来源:https://stackoverflow.com/questions/51380163/canvasrenderingcontext2d-strokerect-still-tries-to-antialias-my-values-instead