Reputation: 304
I'm drawing diagonal lines on an HTML canvas with a specific size, but some of them appear to have different color/opacity than the others. I would like them to have the same color/opacity.
The code I'm using to generate this output is the following:
let artist = {
step: 50,
distanceBetweenLines: 10,
verticalDifferenceInLines: 150,
}
window.onload = function () {
canv = document.getElementById("gc");
ctx = canv.getContext("2d");
ctx.translate(0.5, 0.5);
ctx.lineWidth = "1";
ctx.strokeStyle = "black";
draw();
}
function draw () {
let step = artist.step;
let d = artist.distanceBetweenLines;
let v = artist.verticalDifferenceInLines;
for (let x = 0; x < 500; x += step) {
for (let y = 0; y < 500; y += step) {
let increment = 30;
line({x:x, y: y}, {x:x+increment, y: y+increment});
}
}
}
function line(init, end) {
ctx.beginPath();
ctx.moveTo(init.x, init.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
Why I'm getting this effect on some of the lines?
Upvotes: 2
Views: 524
Reputation: 137016
This is a chrome bug. I opened an issue here.
That's basically a problem with Hardware Acceleration, if you disable it, it will render nicely even in Chrome.
To workaround the issue, you can compose a single bigger path which will contain all your lines and call stroke()
only once:
let artist = {
step: 50,
distanceBetweenLines: 10,
verticalDifferenceInLines: 150,
}
window.onload = function() {
canv = document.getElementById("gc");
ctx = canv.getContext("2d");
ctx.translate(0.5, 0.5);
ctx.lineWidth = "1";
ctx.strokeStyle = "black";
draw();
}
function draw() {
let step = artist.step;
let d = artist.distanceBetweenLines;
let v = artist.verticalDifferenceInLines;
// a single big path
ctx.beginPath();
for (let x = 0; x < 500; x += step) {
for (let y = 0; y < 500; y += step) {
let increment = 30;
line({
x: x,
y: y
}, {
x: x + increment,
y: y + increment
});
}
}
// stroke only once
ctx.stroke();
}
function line(init, end) {
ctx.moveTo(init.x, init.y);
ctx.lineTo(end.x, end.y);
}
<canvas id="gc" width="500" height="500"></canvas>
But for this exact drawing, it would even be better to use a CanvasPattern:
// An helper function to create CanvasPatterns
// returns a 2DContext on which a simple `finalize` method is attached
// method which does return a CanvasPattern from the underlying canvas
function patternMaker( width, height ) {
const canvas = document.createElement( 'canvas' );
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext( '2d' );
ctx.finalize = (repetition = "repeat") => ctx.createPattern( canvas, repetition );
return ctx;
}
const canvas = document.getElementById("gc");
const ctx = canvas.getContext("2d");
const step = 50;
const offset = 30;
const patt_maker = patternMaker( step, step );
patt_maker.translate( 0.5, 0.5 );
patt_maker.moveTo( 0, 0 );
patt_maker.lineTo( offset, offset );
patt_maker.stroke();
const patt = patt_maker.finalize();
ctx.fillStyle = patt;
ctx.fillRect( 0, 0, canvas.width, canvas.height );
<canvas id="gc" width="500" height="500"></canvas>
Upvotes: 2