호 (arc), 베지어 곡선 (bezier), 직사각형 그리기에 대해 알아보자. 😐

안녕하세요! 두두코딩 입니다 ✋
오늘은 호 (arc), 베지어 곡선 (bezier), 직사각형 그리기에 대해 알아보겠습니다.

이전 포스팅과 연계되어 진행되며, 포스팅 참고하시면 더 많은 지식을 배울 수 있습니다!

🖇 소스코드에 마우스를 올리고 copy 버튼을 누를 경우 더 쉽게 복사할 수 있습니다!

궁금한 점, 보안점 남겨주시면 성실히 답변하겠습니다. 😁
+ 감상평 댓글로 남겨주시면 힘이됩니다. 🙇

호 (arc)

호나 원을 그리기 위해서 우리는 arc() 혹은 arcTo()메소를 사용한다. 두 함수의 차이는 각도로 내가 원하는 만큼 그리느냐 혹은 주어진 대상의 위치까지 호를 그리느냐의 차이이다. 좀 더 자세하게 보자.

arc (x, y, radius, startAngle, endAngle, anticlockwise)

위의 함수는 x, y의 시작점에서 반지름 radius 을가지고 start,end Angle까지 anticlockwise (시계 / 반시계) 방향으로 원 또는 호를 그려라 라고 주문하는 함수이다.

arcTo(x1, y1, x2, y2, radius)

위 함수는 시작점 (x1, y1)에서 (x2, y2) 까지 반지름 raius를 가지고 호를 그려라 라는 함수이다.

해당 함수를 알기 위해서는 radian의 개념을 알아야한다. Javascript에서는 각도라는 개념이 없고, radian으로 환산해서 사용한다. 해당 개념은 수학적 개념이 포함되어있어, 여기 를 클릭해 확인해보기 바란다. (아주 쉽게 그림으로 설명하고 있다.🤗)

링크를 통해 확인하거나 radian의 개념을 알고 있다면, Math.PI 가 180도를 나타낸 다는 것을 알 수 있다.

아래의 예시를 통해 호 arc 어떻게 그리는지 확인해보자. (예시가 이전 것들 보다는 어려울 수 있다. 차근차근 따라하면서 이해해보자.)

See the Pen graphic by 13634816 (@13634816) on CodePen.

위의 예시를 보면, context를 획득하고 for loop를 돌기 전 beginPath()로 내가 그림을 그릴 부분을 재 지정한다고 초기화 하는 부분을 볼 수 있다.

radius 같은 경우는 반지름 인데, 현재는 23 으로 고정을 해뒀지만, 코드를 연습할 때는 반지름의 크기를 변형해보고, 실제 원의 크기가 바뀌는지 확인해보는 것이 좋다.

그리고 각도 같은 경우 Math.PI가 180도 인데, 지속적으로 90도를 더해 원의 모양을 변경시켜주는 것을 볼 수 있다.

anticlockwise 같은 경우 arc()의 마지막 인자로 원을 시계방향으로 그릴 것인가 반시계 방향으로 그릴 것인가를 결정하는 부분이다. 해당 부분이 true로 되어져 있다면, 반시계 방향으로 그림을 그린다. false일 경우 시계방향으로 그릴 수 있으니 잘 알아두자.

예시를 짜면서 arc()가 어떤 것인지 이해하는게 좋다. 실제 그림을 보면서, 어떤 변수가 어떻게 쓰이는지 확인해보기 바란다.

베지어 곡선

베지어 곡선의 이론은 설명이 잘나와있는 블로그를 참고했다.

베지어 곡선 혹은 베지어 곡선은 n개의 점으로 부터 얻어지는 n - 1 1차 곡선으로 수치 해석 분야에서 상당히 중요한 위치를 차지하고 있다.

우리가 흔히 사용하는 부분은 포토샵의 펜 툴을 이용한 이미지를 그리거나 CSS 애니메이션에서도 볼 수 있다.

베지어 곡선은 조절점을 이용하여 만든다. 두 개의 점을 이어야 하기 때문에 조절점은 2개이상으로 구성된다. 다만, 조절점이 많을 수록 계산하는데 오래 걸린다.

아래의 예시를 통해 조절점이 3개인 경우 어떻게 곡선을 구성하는지 확인해보자.

bezier

우리는 보통 조절점 n개인 경우 n - 1차 베지어 곡선이라고 표현한다. 해당 예시는 2차 베지어 곡선이라고 생각하면 된다.

조절점은 보통 시작점, 끝점, 제어점으로 나뉜다. 제어점을 통해 curve를 조절하는데, 2차 베지어 부터 제어점을 활요하는 것을 볼 수 있다. 우선 함수를 통해 확인해보자.

베지어 곡선을 그리는 방법은 아래의 함수를 이용하면 된다.

quadraticCurveTo(cp1x, cp1y, x, y)

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

아래의 사진을 참고해보자.

시작점, 끝점 은 파란색, 제어점을 빨간색으로 표시되어져있다.

bezier

보통 이차 및 삼차 와 같은 curve가 있는 베지어 곡선을 사용하는 것은 어려울 수 있다. 우리가 흔히 사용하는 Adobe illustrator와 같은 벡터 드로잉 소프트웨어를 사용한다. 눈으로 보면서 조절 할 수 있지만 직접적인 시각적 피드백을 받을 수 없은 해당 함수들 같은 경우 처음 사용하면 어려울 수 있다.

다만, 연습을 통한다면 더욱 복잡형 도형을 쉽게 그릴 수 있을 것이다.

See the Pen graphic by 13634816 (@13634816) on CodePen.

직사각형

우리는 이전 포스팅을 통해 직사각형 그리기에 대해 알아보았다. 해당 포스팅에서 직사각형을 그리는 함수 3가지를 다뤘는데, 직사각형을 그리기 위한 함수가 추가로 하나가 더 있어 소개하고자 한다.

직사각형을 그리기위한 새로운 메소드 rect().

rect(x, y, width, height)

rect()를 사용하기 위해서는 (x, y) 좌표와 width, height를 전달하면 된다.

해당 함수가 다른 직사각형을 그리는 함수 3가지와 다른 점은 "즉시 랜더링을 하지 않음" 이다. 그리는 부분과 랜더링 부분이 나눠져있다는 점이 다른점이다.

구체적으로, fillRect() 라는 함수를 사용한다고 가정해보자. 해당 함수를 사용할 경우 x,y를 기준으로 width, height 만큼 사각형을 그리고 채워 넣을 것이다.

하지만, rect()를 사용한다면, x,y 만큼 width, height 그릴 위치를 선정하고 실제 랜더링 하지 않는다. 해당 함수를 호출 한 후에 fill()이라는 함수를 통해 랜더링을 시작한다. 퍼포먼스를 위해 해당 함수를 만든 것이라 생각한다.

See the Pen graphic by 13634816 (@13634816) on CodePen.

Path2D 오브젝트

위의 직사각형 예제에서 보았 듯이, 캔버스에 객체를 그리는 일련의 경로와 그리기 명령(랜더링) 두 가지 동작을 나눠서 생각할 수 있다. 코드를 단순화 하고 성능 향상 을 위해 최근 브라우저에서 path2D 라는 객체를 제공한다.

해당 객체는 드로잉 명령 캐시 하거나 드로잉 명령 기록 을 할 수 있다. 따라서, 경로를 더 빠르게 다시 실행시킬 수 있다.

Path2D() 객체 생성

new Path2D();   // 기본 생성자
new Path2D(path);   // 복사 생성자
new Path2D(d);    // SVG path 데이터를 넘겨줌

우리가 이전에 배운 moveTo, rect, arc 혹은 quadraticCurveTo 함수들 모두 Path2D에서 사용이 가능하다.

추가로, Path2D 에는 addPath 메소드를 활용해 경로를 결합할 수도 있다.

See the Pen graphic by 13634816 (@13634816) on CodePen.

위의 예시를 보면, 직사각형과 원을 만들고 있다. 해당 도형 모두 Path2D 객체로 저장하며, 나중에 그리는 함수 (랜더링 함수)를 통해 그릴 것이다. fillstroke는 객체를 전달받아 그리는 부분을 볼 수 있다. 해당 부분들은 한줄 한줄 쳐보며 이해하기 바란다.