자바스크립트: 캔버스로 원 그리기 + 원을 n등분하기
캔버스에 대한 기초 사용법은 모질라 web docs에서 볼 수 있습니다.
원 그리기
호(arc) 명령을 이용해서 원을 그릴 수 있습니다.
1
arc(x, y, radius, startAngle, endAngle, anticlockwise)
(x, y) 위치에 원점을 두면서, 반지름 r을 가지고, startAngle 에서 시작하여 endAngle 에서 끝나며 주어진 anticlockwise 방향으로 향하는 (기본값 false - 시계방향 회전) 호를 그리게 됩니다.
예제 코드를 살펴보겠습니다. HTML 기본 토대는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body onload="draw();">
<canvas width="500" height="500" id="canvas"></canvas>
<script>
............
</script>
</body>
</html>
body 요소의 로드가 완료되면 스크립트 부분의 draw() 함수를 실행합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const geom = {
x: 100,
y: 100,
radius: 90,
statrAngle: 0,
endAngle: 360,
anticlockwise: false
}
function degToRad(deg) {
return (Math.PI / 180) * deg
}
//
function draw() {
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
ctx.beginPath()
// arc(x, y, radius, startAngle, endAngle, anticlockwise)
ctx.arc(geom.x, geom.y, geom.radius, degToRad(geom.statrAngle), degToRad(geom.endAngle), geom.anticlockwise)
console.log(degToRad(geom.statrAngle), degToRad(geom.endAngle))
ctx.stroke()
}
변수 geom은 설정 정보를 모아놓은 객체 변수입니다. 함수 degToRad는 각도(degree)를 라디언(radian)으로 변환하여 리턴합니다. 제가 사실 문과 출신이라 라디언이 뭔지 잘 몰라서 이하 내용에서는 전부 각도를 사용한 뒤 degToRad 를 이용해 변환하겠습니다. 함수 draw는 캔버스에 그림을 그리는 부분입니다.
ctx는 컨텍스트 정보를 담고 있는 변수로 컨텍스트는 지금 단계에서는 ‘캔버스에 그림을 그리는 방법‘이라고 생각하면 될 것 같습니다. 2D, 또는 3D 등이 있는데 여기에서 사용할 것은 2차원으로 그림을 그리는 것이므로 canvas.getContext("2d") 라고 작성하여 2차원 컨텍스트를 가져옵니다.
ctx.beginPath()는 경로(path)를 시작하는 명령입니다. 경로는 사각형 이외의 모든 도형에서 사용하는 점들의 집합(선)입니다. 경로를 끝내는 명령은 ctx.closePath() 입니다. arc는 호(arc)를 그리는데 이 호들이 모이면 원이 될 수 있습니다. ctx.stroke()는 작성된 경로를 바탕으로 시각적으로 보이는 외곽선을 그립니다.
arc 명령에서 x, y는 중심점의 위치입니다. radius는 반지름입니다. 단위는 캔버스에서 사용하는 고유 단위입니다. (픽셀과 비슷하나 1:1 대응하지는 않습니다.) startAngle, endAngle은 시작 각과 끝 각인데 사용 단위는 라디언(radian)입니다. anticlockwise는 회전 방향을 지정하는 것으로 기본값은 false입니다. (반시계방향 설정인데 false이므로 시계 방향 회전합니다.)
startAngle이 0인 경우 3시 방향을 가리키는 것이니 주의하시기 바랍니다.
[caption id=”attachment_1986” align=”alignnone” width=”350”]
startAngle, endAngle 값의 변화에 따른 그림들[/caption]
원을 n등분하여 그리기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function draw(){
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const geom = {
x: 120,
y: 120,
radius: 100,
statrAngle: 0,
endAngle: 360,
anticlockwise: false
}
let part = 6
let eachDeg = 360 / part
//
ctx.beginPath()
for(let i = 0; i <= part; i++){
// arc(x, y, radius, startAngle, endAngle, anticlockwise)
ctx.arc(geom.x, geom.y, geom.radius, degToRad(i * eachDeg), degToRad(i * eachDeg + eachDeg), geom.anticlockwise)
ctx.lineTo(geom.x, geom.y)
}
ctx.stroke()
}
원을 n 으로 나눠 그리는 예제입니다. 피자 나누는 그림을 생각하면 될 것 같습니다. part의 숫자에 따라 나누는데, lineTo()은 현재 경로의 위치에서 특정 좌표까지 선을 그리면서 이동하는 명령입니다. 360도를 n으로 나누면 각 등분한 도형 당 필요한 각도가 계산되고, for문을 돌리면서 필요한 각도를 곱하는 식으로 원을 그리게 됩니다.
[caption id=”attachment_1987” align=”alignnone” width=”321”]
6등분[/caption]
[caption id=”attachment_1988” align=”alignnone” width=”318”]
11등분[/caption]
예제: 피자를 n등분으로 나누기
여기에 이미지를 입히고 입력값을 받아 피자를 n등분하는 예제 프로그램을 만들어보도록 하겠습니다. (jsfiddle에서 보기)
https://gist.github.com/ayaysir/d43d7f51204a3f2fdb49e012ca8786a2
new Image()로 인스턴스를 만들어 이미지를 불러오고, 그 이미지를 ctx.drawImage(image객체, 시작점x, 시작점y)로 그린 다음 n등분한 원의 외곽선을 검은색으로 그려 피자를 칼로 자른것 같은 이미지를 보여줍니다.
https://gph.is/g/Z2dBKjL
