How to get rid of faint dark lines in a pie chart with canvas?

Viewed 42

I'm making a color circle that acts like a pie chart, which is made from a list [0..n]. The issue is that there are some faint dark lines between each slice. It is especially noticeable on the green colors as shown here.

chart image

Here is my code:

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

const list = Array.from({ length: 100 }, (_, i) => i + 1); // generate list

context.fillStyle = '#000000';
context.fillRect(0, 0, canvas.width, canvas.height);
const center = [Math.floor(canvas.width / 2), Math.floor(canvas.height / 2)];
const radius = Math.min(center[0], center[1]);
let prevAngle = 0;
for (let i = 0; i < list.length; i++) {
  const hue = 255 - (list[i] / list.length) * 360;
  const color = `hsl(${hue},100%,50%)`;
  const angle = prevAngle + (1 / list.length) * Math.PI * 2;
  context.fillStyle = color;
  context.strokeStyle = color;
  context.beginPath();
  context.arc(center[0], center[1], radius, prevAngle, angle);
  context.lineTo(center[0], center[1]);
  context.fill();
  context.stroke();
  prevAngle = angle;
}
<canvas id="canvas" width="600" height="600"></canvas>

1 Answers

It looks like this is due to imprecisions in subpixels. You could make it less obvious by making your lines a tiny bit thicker:

context.lineWidth = 1.5;

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

const list = Array.from({ length: 100 }, (_, i) => i + 1); // generate list

context.fillStyle = '#000';

context.lineWidth = 1.5; // <-------------

context.fillRect(0, 0, canvas.width, canvas.height);
const center = [Math.floor(canvas.width / 2), Math.floor(canvas.height / 2)];
const radius = Math.min(center[0], center[1]);
let prevAngle = 0;
for (let i = 0; i < list.length; i++) {
  const hue = 255 - (list[i] / list.length) * 360;
  const color = `hsl(${hue},100%,50%)`;
  const angle = prevAngle + (1 / list.length) * Math.PI * 2;
  context.fillStyle = color;
  context.strokeStyle = color;
  context.beginPath();
  context.arc(center[0], center[1], radius, prevAngle, angle);
  context.lineTo(center[0], center[1]);
  context.fill();
  context.stroke();
  prevAngle = angle;
}
<canvas id="canvas" width="600" height="600"></canvas>

Related