For the purpose of improving myself and because I was bored, I was learning the canvas tags in html by following the doc of mozilla and we were drawing a face there. I tried to make the face as given by mozilla, but lines appeared on my face due to the values and I don't know why.
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d")
ctx.beginPath()
ctx.arc(75, 75, 60, 0, Math.PI * 2, true)
ctx.moveTo(40, 40)
ctx.arc(50, 50, 10, 0, Math.PI * 2, true)
ctx.moveTo(60, 50)
ctx.arc(100, 50, 10, 0, Math.PI * 2, true)
ctx.moveTo(110, 110)
ctx.arc(80, 110, 30, 0, Math.PI, true)
ctx.stroke()
<canvas class="canvas" width="150" height="150"></canvas>
Expected face:
Result face:
As you can see, I'm talking about unwanted lines on the face.
All I know and discovered is that for some reason the x
value of the moveTo
should be as much as the radius of the circle and the y
values should be the same - but I don't know why. I wanted to ask you why this is the case.
In summary, I haven't figured out why, but for some reason, when I play with the values or when I make the values incompatible, a line appears.
beginPath()
starts a new path.arc()
adds a circle segment to the path.moveTo()
starts a new segment at that location and the path continues from there.arc()
adds to the path segment starting from the moveTo()
location to the beginning of the circle and then around the circle.stroke(
) draws all the path segments that were defined since the beginPath()
So to draw the face, you need to remove the moveTo()
calls and wrap each arc()
in a beginPath()
and stroke()
call. See this first snippet.
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d")
ctx.beginPath()
ctx.arc(75, 75, 60, 0, Math.PI * 2, true)
ctx.stroke()
ctx.beginPath()
ctx.arc(50, 50, 10, 0, Math.PI * 2, true)
ctx.stroke()
ctx.beginPath()
ctx.arc(100, 50, 10, 0, Math.PI * 2, true)
ctx.stroke()
ctx.beginPath()
// EDIT Change x and y slightly
ctx.arc(75, 90, 30, 0, Math.PI, false)
ctx.stroke()
canvas {
box-shadow: 2px 2px 5px salmon;
}
<canvas class="canvas" width="300" height="180"></canvas>
In this second snippet is your code with the moveTo() coordinates circled in red. You can see that lines are drawn from the moveTo() coordinates to the beginning of the arc's path segment.
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath()
ctx.arc(75, 75, 60, 0, Math.PI * 2, true)
ctx.moveTo(40, 40)
ctx.arc(50, 50, 10, 0, Math.PI * 2, true)
ctx.moveTo(60, 50)
ctx.arc(100, 50, 10, 0, Math.PI * 2, true)
ctx.moveTo(110, 110)
ctx.arc(80, 110, 30, 0, Math.PI, true)
ctx.stroke()
// Draw a dot at all of the moveTo() coordinates
dot(40, 40);
dot(60, 50);
dot(110, 110);
function dot(x, y) {
ctx.strokeStyle = "red"
ctx.beginPath();
ctx.arc(x, y, 4, 0, Math.PI * 2)
ctx.stroke();
}
<canvas class="canvas" width="300" height="180"></canvas>
In this third snippet the original mozilla coordinates are used with moveTo() coordinates circled in red. You don't see any straight lines because the "lines" are 0 length, since the moveTo() coordinates are the same as the location where the arc's start their path segment.
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false); // Mouth (clockwise)
ctx.moveTo(65, 65);
ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // Left eye
ctx.moveTo(95, 65);
ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // Right eye
ctx.stroke();
// Draw a dot at all of the moveTo() coordinates
dot(110, 75);
dot(65, 65);
dot(95, 65);
function dot(x, y) {
ctx.strokeStyle = "red"
ctx.beginPath();
ctx.arc(x, y, 4, 0, Math.PI * 2)
ctx.stroke();
}
<canvas class="canvas" width="300" height="180"></canvas>