Canvas - 02
캔버스(canvas)를 이용한 도형 그리기
그리드
위 그림을 보면 캔버스와 기본 그리드가 놓인 것을 볼 수 있다.
기본적으로 그리드의 1단위는 캔버스의 1픽셀과 같다.
이 그리드의 원점은 좌측 상단의 (0,0)이다.
모든 요소들은 이 원점을 기준으로 위치한다.
그렇기 때문에 파란 사각형의 좌측상단은 왼쪽에서 x픽셀, 위에서 y픽셀만큼 떨어진 것이라 볼 수 있고, 이 사각형의 좌표는 x,y가 된다.
직사각형 그리기
-
SVG와는 다르게 <canvas>는 오직 하나의 원시적인 도형만을 제공한다. 바로 직사각형이다. 다른 모든 도형들은 무조건 하나 혹은 하나 이상의 path와 여러 점으로 이어진 선으로 만들어진다.
복잡한 도형을 그리기 위해서는 path drawing 함수들을 통해 그릴 수 있다. -
직사각형을 그리는 세가지 함수
- fillRect(x, y, width, height)
- 색칠된 직사각형을 그린다.
- strokeRect(x, y, width, height)
- 직사각형 윤관선을 그린다.
- clearRect(x, y, width, height)
- 특정 부분을 지우는 직사각형이며, 이 지워진 부분은 완전히 투명해진다.
- fillRect(x, y, width, height)
-
각각 세 함수는 모두 같은 변수를 가진다. x, y는 캔버스의 좌측상단에서 사각형의 위치를 뜻하며, width와 height는 사각형의 크기를 뜻한다.
직사각형 도형 예제
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);
}
}
fillRect()함수는 가로세로 100픽셀 사이즈의 검정 사각형을 그리고 이후 clearRect()함수가 60 x 60 픽셀의 사각형 크기로 도형 중앙을 지우게 된다.
그리고 strokeRect()가 빈 공간안에서 50 x 50픽셀 사이즈의 윤곽선만 있는 사각형을 만든다.
여기서 볼 수 있 듯이 지웠다고 해서 지속되는 것이 아닌 마치 붓과 지우개를 지우고 다시 붓을 쓰듯 canvas를 그리는 순서에 맞게 그려진다.
경로 그리기
경로(path)는 직사각형 이외의 유일한 원시적인 도형이다.
경로는 점들의 집합이며, 선의 한 부분으로 연결되어 여러가지 도형, 곡선을 이루고 두께와 색을 나타내게 된다. 경로나 하위 경로(sub-path)는 닫힐 수 있다.
경로 만들기 순서
- 경로를 생성한다.
- 그리기 명령어를 사용하여 경로상에 그린다.
- 경로가 한번 만들어졌다면, 경로를 렌더링 하기 위해서 윤곽선을 그리거나 도형 내부를 채울 수 있다.
경로를 그리는 함수
- beginPath()
- 새로운 경로를 만든다. 경로가 생성되었다면 이후 그리기 명령들은 경로를 구성하고 만드는데 사용된다.
- Path 메소드
- 물체를 구성할 때 필요한 여러 경로를 설정하는데 사용하는 함수이다.
- closePath()
- 현재 하위 경로의 시작 부분과 연결된 직선을 추가한다.
- stroke()
- 윤곽선을 이용하여 도형을 그린다.
- fill()
- 경로의 내부를 채워서 내부가 채워진 도형을 그린다.
- 경로를 만들기 위한 첫번째 단계는 beginPath() 메소드를 사용하는 것이다. 내부적으로, 경로는 도형을 이루는 하위경로(선, 아치 등)들의 집합으로 이루어져 있다. 이 메소드가 호출될 때 마다, 하위 경로의 모음은 초기화되며, 우리는 새로운 도형을 그릴 수 있게 된다.
참고
현재 열린 path가 비어있는 경우(beginPath() 메소드를 사용한 직 후, 혹은 캔버스를 새로 생성한 직후), 첫 경로 생성 명령은 실제 동작에 상관 없이 moveTo()로 여겨진다.
그러기에 경로를 초기화한 직후에는 항상 명확하게 시작위치를 설정해 두는 것이 좋다.
-
두번째 단계는 실제로 경로가 그려지는 위치를 설정하는 메소드를 호출한다.
-
세번째 단계는 선택사항으로 closePath() 메소드를 호출하는 것이다. 이 메소드는 현재 점 위치와 시작점 위치를 직선으로 이어서 도형을 닫는다. 이미 도형이 닫혀있거나 한 점만 존재한다면, 이 메소드는 아무것도 하지 않는다.
참고
fill()메소드 호출 시 , 열린 도형은 자동으로 닫히게 되므로 closePath()메소드를 호출하지 않아도 된다. 이것은 stroke()메소드에는 적용되지 않는다.
삼각형 그리기
function draw(){
let canvas = document.getElementById('canvas');
if(canvas.getContext){
let ctx = canvas.getContext('2d');
console.log(ctx);
// 붉은색 물감에 펜을 뭍히고
ctx.fillStyle = "#f00"
//선을 그릴 펜을 잡고
ctx.beginPath();
//도화지에 점을 찍고
ctx.moveTo(75,50);
//선을 100, 75 픽셀로 이동
ctx.lineTo(100,75);
//도화지에 안떼고 이어서 선을 100,25로 이동
ctx.lineTo(100,25);
//stroke로 보면 펜이 이동한 경로를 볼 수 있다.
//ctx.stroke();
//fill를 사용하면 마지막 펜의 위치를 원점으로 이동시켜 내부를 채운다.
ctx.fill();
}
}
펜(pen) 이동하기
가장 유용한 함수 중에 실제로 어떤 것도 그리지 않지만 위에서 언급한 경로의 일부가 되는 moveTo() 함수가 있다. 이는 펜이나 종이 위에서 들어 옆으로 옮기는 것이라 볼 수 있다.
- moveTo(x,y)
- 펜은 x와 y로 지정된 좌표로 옮긴다.
캔버스가 초기화 되었거나 beginPath() 메소드가 호출되었을 때 특정 시작점을 설정하기 위해 moveTo() 함수를 사용하는 것이 좋다. 또한 moveTo() 함수는 연결되지 않은 경로를 그리는데에도 사용 할 수 있다.
다음은 스마일을 그리기위해 중간지점 마다 펜을 들어 지점을 찍어서 다음 도형을 만든 예시이다.
function draw(){
let canvas = document.getElementById('canvas');
if(canvas.getContext){
let ctx = canvas.getContext('2d');
ctx.beginPath();
// 겉의 원형을 그린다.
//x,y,반지름, 시작라디안, 종료라디안, 시계방향
ctx.arc(75,75, 50, 0, Math.PI * 2, true);
//펜을 들어 다음 지점을 찍는다.
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI, false);
//펜을 들어 다음 지점을 찍는다.
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI * 2, true);
//펜을 들어 다음 지점을 찍는다.
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI * 2, true);
ctx.stroke();
}
}
만약 moveTo를 하지 않으면 연결된 선을 확인 할 수 있다.
선
직선을 그리기 위해서는 lineTo() 메소드를 사용할 수 있다.
- lineTo(x,y)
- 현재의 드로잉 위치에서 x와 y로 지정된 위치까지 선을 그립니다.
이 메소드는 선의 끝점의 좌표가 되는 x와 y의 두개의 인자가 필요하다. 시작점은 이전에 그려진 경로에 의해 결정되고, 이전 경로의 끝점이 다음 그려지는 경로의 시작점이 된다.
또한 시작점은 moveTo()메소드를 통해 병경될 수 있다.
2개의 삼각형 그리기
function draw(){
let canvas = document.getElementById('canvas');
if(canvas.getContext){
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(25,25);
ctx.lineTo(105,25);
ctx.lineTo(25,105);
//fill은 자동으로 닫아주기 때문에 아래는 필요없다.
//ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(125,125);
ctx.lineTo(125,45);
ctx.lineTo(45,125);
//열린 공간을 닫아준다.
ctx.closePath();
ctx.stroke();
}
}
호
호나 원을 그리기위해서는 arc() 혹은 arcTo()메소드를 사용한다.
- arc(x, y, radius, startAngle, endAngle, anticlockwise)
- (x, y) 위치에 원점을 두면서, 반지름 r을 가지고, startAngle 에서 시작하여 endAngle 에서 끝나며 주어진 anticlockwise 방향으로 향하는 (기본값은 시계방향 회전) 호를 그리게 된다.
- x 와 y는 호를 그릴 때 필요한 원점 좌표입니다. 반지름(radius) 은 말 그대로 호의 반지름을 뜻하고 startAngle 및 endAngle 매개 변수는 원의 커브를 따라 호의 시작점과 끝점을 라디안 단위로 정의한다. 이 변수들은 x축을 기준으로 계산된다. Boolean 값을 가지는 anticlockwise 변수는 true일 때 호를 반시계 방향으로 그리게 되며, 그렇지 않을 경우에는 시계 방향으로 그리게 된다.
참고
arc 함수에서 각도는 각이 아닌 라디안 값을 사용한다.
따라서 각도를 라디안으로 바꾸려면 다음의 코드를 사용할 수 있다.radians = (Math.PI/180)*degrees
- arcTo(x1, y1, x2, y2, radius)
- 주어진 제어점들과 반지름으로 호를 그리고, 이전 점과 직선으로 연결합니다.
다양한 호 그리기
function draw(){
let canvas = document.getElementById('canvas');
if(canvas.getContext){
let ctx = canvas.getContext('2d');
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
ctx.beginPath();
let x = 50 * j + 25; //j가 증가할 수 록 x가 50만큼 이동
let y = 50 * i + 25; // i가 증가할 수록 y가 50만큼 이동
let radius = 20; // 반지름은 20로 고정
let startAngle = 0; // 시작점도 0으로 고정
let endAngle = Math.PI + (Math.PI * j) / 2;
//i가 2로 나누어질때 나머지가 0이되면 false, 아니면 true;
let anticlockwise = i % 2 == 0 ? false : true;
ctx.arc(x,y,radius, startAngle, endAngle, anticlockwise);
if(i>1){
ctx.fill(); // i가 2과 3일때
}else{
ctx.stroke(); // i가 0과 1일때
}
}
}
}
}
Author And Source
이 문제에 관하여(Canvas - 02), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@km2535/Canvas-02저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)