如何去除重叠笔画

How to remove overlapping stroke

我正在尝试绘制一组圆圈,这些圆圈应该打断一组直线。 如果圆圈彼此远离,一切看起来都很好,但如果圆圈重叠 - 下面会出现笔画。

关于如何在圆圈重叠时删除此笔画的任何提示? 这就是我要说的:

这是我的代码:

let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d');

document.body.style.backgroundColor = "#121212";
ctx.lineWidth = 1;
ctx.fillStyle = '#121212';
ctx.strokeStyle = '#9f9999';
ctx.lineCap = "round";

let width = canvas.width;
let height = canvas.height;

let lines = new Array(height);
let singleLine = new Array(width);
let step = 30;

for (let y = step; y < height; y += step) {
  ctx.beginPath();
  for (let x = step; x < width; x += step) {

    if (Math.random() < 0.85) {
      ctx.lineTo(x, y);
    } else {
      drawCircle(y, x);
    }
  }
  ctx.stroke();
  ctx.fill();
}


function drawCircle(x, y) {
  ctx.arc(y, x, 20, Math.PI, 0, false);
}
<canvas id="myCanvas"></canvas>

发生这种情况是因为您通过 fill() 覆盖交点的方式将覆盖 填充区域边界上的一半描边。这是圆形部分的 okay-ish,但两个圆弧之间的底部(隐式)lineTo 的下半部分仍然可见:

const ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "rgba(255, 0, 0, 0.25)";

ctx.lineTo(30, 50);
ctx.lineTo(60, 50);
ctx.arc(90, 50, 20, Math.PI, 0);
ctx.arc(120, 50, 20, Math.PI, 0);
ctx.lineTo(150, 50);
ctx.lineTo(180, 50);
ctx.stroke();
ctx.fill();

// a zoomed in version in case it's not visible enough
const zoom = document.querySelectorAll("canvas")[1].getContext("2d");
zoom.scale(4, 4);
zoom.imageSmoothingEnabled = false;
zoom.drawImage(ctx.canvas, -70, -20);
canvas{ vertical-align: middle }
<canvas width=200></canvas>zoomed in: <canvas></canvas>

我最初的想法是在每个重叠的凹凸部分上绘制矩形,但更好的方法是 :在描边后稍微向下扩展填充,然后用背景颜色填充路径。这确保重叠线的底部笔划也被填充。

const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d");
document.body.style.backgroundColor = "#121212";
ctx.lineWidth = 1;
ctx.fillStyle = "#121212";
ctx.strokeStyle = "#9f9999";
ctx.lineCap = "round";

const {width, height} = canvas;
const step = 30;

for (let y = step; y < height; y += step) {
  ctx.beginPath();

  for (let x = step; x < width; x += step) {
    if (Math.random() < 0.55) {
      ctx.lineTo(x, y);
    }
    else {
      ctx.arc(x, y, 20, Math.PI, 0, false);
    }
  }

  ctx.stroke();
  ctx.lineTo(width - step, y + 1);
  ctx.lineTo(step, y + 1);
  //ctx.fillStyle = "red"; // to debug
  ctx.fill();
}
<canvas></canvas>