Andrew Rasmussen
Andrew Rasmussen

Reputation: 15099

Why do overlapping canvas lines darken?

I'm drawing a bunch of lines next to each other, each with width 1. The entire canvas has a scale that is zoomed out so that they are presumably rendered on top of each other.

If they're all pure green (#00ff00), why does the overlap darken? Screenshot and code sample attached.

Screenshot

render(props) {
  const {
    context,
    x, y,
  } = props;

  context.lineWidth = 1;
  context.fillStyle = '#000';
  this._pings.forEach((ping, i) => {
    context.beginPath();
    context.moveTo(x + i, y);
    context.lineTo(x + i, Math.max(y - ping, y - 100));
    context.strokeStyle = pingToColor(ping);
    context.stroke();
  });
}

Upvotes: 0

Views: 602

Answers (1)

user1693593
user1693593

Reputation:

It's because the line is drawn at its center so 0.5 pixel bleeds to each side which forces sub-pixeling to take place, hence two semi-transparent lines are drawn next to each other.

To solve simply offset the x position 0.5 pixel by using either a translate or adding the offset to the x positions:

Snapshot

var ctx = c.getContext("2d");
ctx.strokeStyle = "#00ff00";

// Draw some random overlapping lines
for(var i = 0, x ,y; i < 500; i++) {
  x = (Math.random() * 150)|0;
  y = Math.random() * 100 + 50;
  
  ctx.moveTo(x, y>>1);          // non-offset
  ctx.lineTo(x, y);
  
  ctx.moveTo(x+150+0.5, y>>1);  // offset 0.5 (ignore 150)
  ctx.lineTo(x+150+0.5, y);
}
ctx.stroke();

ctx.fillStyle = "#fff";
ctx.fillRect(150,0,1,150);
ctx.fillText("Integer position", 5, 10);
ctx.fillText("Offset +0.5", 155, 10);
<canvas id=c style="background:#000"></canvas>

Upvotes: 2

Related Questions