我正在尝试模仿在互联网上找到的a pattern,但是在中间以及尝试在顶部连接另一组圆圈时,出现奇怪的线条。

另外,当我尝试填充时,它会变成全黑。



console.log("grid");

var canvas = document.getElementById("canvas");
var image_b = document.getElementById("brown");
var image_g = document.getElementById("grey");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;



var ctx = canvas.getContext("2d");

var side = 160;
var side2 = 150;



ctx.strokeStyle = 'black';
ctx.fillStyle = 'white';

function draw() {

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;


  ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
  var widthNbr = Math.ceil(window.innerWidth / side) + 1;
  var heightNbr = Math.ceil(window.innerHeight / side) + 1;

  var counter = 0;
  for (var i = 0; i < widthNbr; i++) {
    for (var j = 0; j < heightNbr; j++) {



      ctx.beginPath();

      var x = side * i + side / 2;
      var y = side * j + side / 2;

      var a = side * i + side / 2;
      var s = side * j + side / 2;

      var d = side * i + side / 2;
      var f = side * j + side / 2;

      var g = side * i + side / 2;
      var h = side * j + side / 2;

      var q = side * i + side / 2;
      var w = side * j + side / 2;

      var o = side * i + side / 2;
      var p = side * j + side / 2;


      var x1 = side2 * i + side2;
      var y1 = side2 * j + side2;

      var a1 = side2 * i + side2;
      var s1 = side2 * j + side2;

      var d1 = side2 * i + side2;
      var f1 = side2 * j + side2;

      var g1 = side2 * i + side2;
      var h1 = side2 * j + side2;

      var q1 = side2 * i + side2;
      var w1 = side2 * j + side2;

      var o1 = side2 * i + side2;
      var p1 = side2 * j + side2;


      ctx.arc(x, y, side / 2, 0, Math.PI * 2);
      ctx.arc(a, s, side / 2.5, 0, Math.PI * 2);
      ctx.arc(d, f, side / 3.5, 0, Math.PI * 2);
      ctx.arc(g, h, side / 5.3, 0, Math.PI * 2);
      ctx.arc(q, w, side / 9, 0, Math.PI * 2);
      ctx.arc(o, p, side / 18, 0, Math.PI * 2);
      ctx.lineWidth = 5;

      ctx.arc(x1, y1, side2 / 2, 0, Math.PI * 2);
      ctx.arc(a1, s1, side2 / 2.5, 0, Math.PI * 2);
      ctx.arc(d1, f1, side2 / 3.5, 0, Math.PI * 2);
      ctx.arc(g1, h1, side2 / 5.3, 0, Math.PI * 2);
      ctx.arc(q1, w1, side2 / 9, 0, Math.PI * 2);
      ctx.arc(o1, p1, side2 / 18, 0, Math.PI * 2);




      ctx.stroke();
      // ctx.fill();

      ctx.closePath();
      counter++;


    }
  }

}

draw();

<canvas id="canvas"></canvas>

最佳答案

您必须将“画布路径”绘图视为纸上的铅笔绘图:

在路径声明(beginPath)之后,当您说ctx.arc(x, y, rad, 0, Math.PI*2)时,笔将移至坐标(xy),并且因为xyarc的中心位置它将被放置在距该中心rad距离处以绘制圆。您的0告诉它从3点开始,因此在这种情况下,我们只需要将此rad添加到x值即可。

此时,您的笔在纸上。

它绘制圆弧,当您告诉它arc(x1, y1, rad, ...)时,它将直接转到坐标(x1+rady1)并绘制新的圆弧。

这里的问题是您从未告诉过它要从纸上抬起铅笔,因此您可以看到从第一个弧的最后一个点到下一个弧的第一个点的直线。

幸运的是,Canvas API附带了一组方便的操作,“ Raise_the_pen_and_move_to_coordinates_x,y_without_ruining_my_paper”简称为moveTo

通过告诉上下文轻轻地抬起铅笔并移至下一个第一个绘制点,然后再实际绘制弧,您将避免所有这些拖尾线。

所以基本上,对于三个弧,它将是:

// initialize a new drawing
ctx.beginPath();
// here we can set it directly because the pen is not on the paper yet
ctx.arc(x, y, rad, 0, Math.PI*2);
// tell it to raise the pen off the paper
//  and to go to the next starting point (3 o'clock in our case)
ctx.moveTo(x1 + rad, y1);
ctx.arc(x1, y1, rad, 0, Math.PI*2);
// once again
ctx.moveTo(x2 + rad, y2);
ctx.arc(x2, y2, rad, 0, Math.PI*2);
// now we've got clear independents arcs
ctx.stroke();


以及您的代码(使用数组btw可以清理很多东西)



var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var ctx = canvas.getContext("2d");

var side = 160;
var side2 = 150;

ctx.strokeStyle = 'black';
ctx.fillStyle = 'white';

function draw() {

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
  var widthNbr = Math.ceil(window.innerWidth / side) + 1;
  var heightNbr = Math.ceil(window.innerHeight / side) + 1;

  var counter = 0;
  for (var i = 0; i < widthNbr; i++) {
    for (var j = 0; j < heightNbr; j++) {

      ctx.beginPath();

      var x = side * i + side / 2;
      var y = side * j + side / 2;

      var a = side * i + side / 2;
      var s = side * j + side / 2;

      var d = side * i + side / 2;
      var f = side * j + side / 2;

      var g = side * i + side / 2;
      var h = side * j + side / 2;

      var q = side * i + side / 2;
      var w = side * j + side / 2;

      var o = side * i + side / 2;
      var p = side * j + side / 2;


      var x1 = side2 * i + side2;
      var y1 = side2 * j + side2;

      var a1 = side2 * i + side2;
      var s1 = side2 * j + side2;

      var d1 = side2 * i + side2;
      var f1 = side2 * j + side2;

      var g1 = side2 * i + side2;
      var h1 = side2 * j + side2;

      var q1 = side2 * i + side2;
      var w1 = side2 * j + side2;

      var o1 = side2 * i + side2;
      var p1 = side2 * j + side2;

      ctx.moveTo(x + side / 2, y);
      ctx.arc(x, y, side / 2, 0, Math.PI * 2);
      ctx.moveTo(a + side / 2.5, s);
      ctx.arc(a, s, side / 2.5, 0, Math.PI * 2);
      ctx.moveTo(d + side / 3.5, f)
      ctx.arc(d, f, side / 3.5, 0, Math.PI * 2);
      ctx.moveTo(g + side / 5.3, h)
      ctx.arc(g, h, side / 5.3, 0, Math.PI * 2);
      ctx.moveTo(q + side / 9, w)
      ctx.arc(q, w, side / 9, 0, Math.PI * 2);
      ctx.moveTo(o + side / 18, p)
      ctx.arc(o, p, side / 18, 0, Math.PI * 2);
      ctx.lineWidth = 5;

      ctx.moveTo(x1 + side2 / 2, y1)
      ctx.arc(x1, y1, side2 / 2, 0, Math.PI * 2);
      ctx.moveTo(a1 + side2 / 2.5, s1)
      ctx.arc(a1, s1, side2 / 2.5, 0, Math.PI * 2);
      ctx.moveTo(d1 + side2 / 3.5, f1)
      ctx.arc(d1, f1, side2 / 3.5, 0, Math.PI * 2);
      ctx.moveTo(g1 + side2 / 5.3, h1)
      ctx.arc(g1, h1, side2 / 5.3, 0, Math.PI * 2);
      ctx.moveTo(q1 + side2 / 9, w1)
      ctx.arc(q1, w1, side2 / 9, 0, Math.PI * 2);
      ctx.moveTo(o1 + side2 / 18, p1)
      ctx.arc(o1, p1, side2 / 18, 0, Math.PI * 2);

      ctx.stroke();

      counter++;

    }
  }

}

draw();

<canvas id="canvas"></canvas>





正如Spencer Wieczorek在上面的评论中正确指出的那样,要获得所需的结果,您还必须将最大的弧填充为白色,但是我让您找到一种方法来进行训练。



另外,关于您在代码中使用的closePath()的小注释,当我们看到有人滥用它的时候,他的名字可能会很令人困惑,但是请注意,它并没有结束您的Path声明。它所做的只是一个lineTo(last_time_I_putted_the_pencil)。在闭合圆的情况下,由于last_time_I_putted_the_pencil === current_pencil_position_on_the_paper,它没有任何作用,但通常是很多问题的根源。



还有一个小注意事项,对于经验丰富的用户(可能在几天/几周内可能是OP):
其他操作使我们可以从纸上抬起头:转换命令。
(主要是setTransform,及其子集transformtranslaterotatescale)。
这些操作将首先抬起笔,然后移动纸张而不是笔。在许多情况下这很方便。
并将其设置回其正常位置,只需调用setTransform(1,0,0,1,0,0)

关于javascript - 试图在圈子之外创建图案吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39458841/

10-09 22:09