1.5 기본적인 드로잉 작업
시계 애플리케이션 만들기
시계 애플리케이션 만들 때 사용되는 메서드
- arc()
- beginPath()
- clearRect()
- fill()
- fillText()
- lineTo()
- moveTo()
- stroke()
- 캔버스는 패스의 윤곽을 그리는
stroke()
를 호출하거나 패스의 내부를 칠하는fill()
을 호출해 추후에 시각화할 수 있는 보이지 않는 패스를 생성하여 도형을 그린다. - 패스의 시작은
beginPath()
메서드를 이용한다. drawCircle()
메서드에서는 패스를 시작할 수 있도록beginPath()
메서드를 호출하고 시계 문자판을 나타내는 원을 그린 다음arc()
메서드를 호출해 원형 패스를 생성한다.- 이렇게 만든 패스는 애플리케이션에서
stroke()
메서드를 호출할 때까지 보이지 않는다.
- 마찬가지로
drawCenter()
메서드에서도beginPath()
메서드,arc()
메서드,fill()
메서드 등을 조합해 색이 칠해진 작은 원을 시계 중앙에 그린다.
- 시계 애플리케이션의
drawNumerals()
메서드에서는 색이 칠해진 텍스트를 캔버스에 그리는fillText()
메서드를 이용해 시계 면을 빙 둘러 숫자를 그린다. arc()
메서드와 달리fillText()
메서드에서는 패스를 생성하지 않는다. 대신, 곧바로 캔버스에 텍스트를 생성한다.
- 그리고
moveTo()
메서드,lineTo()
메서드,stroke()
메서드 등 세가지 메서드를 사용해 시계바늘을 나타내는 선을 그리는drawHand()
메서드를 호출해 시계바늘을 그린다. moveTo()
메서드에서는 그래픽 펜을 캔버스의 특정 위치로 옮기고,lineTo()
메서드에서는 보이지 않는 패스를 캔버스의 정해진 위치에 그리며,stroke()
메서드에서는 현재 패스를 보이게 만든다.
- 시계 애플리케이션에서는 매초 시계 애플리케이션의
drawClock()
함수를 호출하는setInterval()
메서드를 이용해 시계바늘을 움직인다. drawClock()
함수에서는clearRect()
메서드를 이용해 캔버스를 지운 다음 시계를 다시 그린다.
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
FONT_HEIGHT = 15,
MARGIN = 35,
HAND_TRUNCATION = canvas.width / 25,
HOUR_HAND_TRUNCATION = canvas.width / 10,
NUMERAL_SPACING = 20,
RADIUS = canvas.width / 2 - MARGIN,
HAND_RADIUS = RADIUS + NUMERAL_SPACING;
// 함수
// 원주율 : 지름이 1일 때 원둘레 3.14xxxxx
// 원둘레 : 지름 X 원주율
// 원넓이 : 반지름 X 반지름 X 원주율 <- 원을 쪼개서 직사각형으로 만들어보면 된다.
var drawCircle = function () {
context.beginPath();
context.arc(
canvas.width / 2, // 원의 원점 x좌표
canvas.height / 2, // 원의 원점 y좌표
RADIUS, // 원의 반지름
0, // 0도부터 그리기 시작해서
Math.PI * 2, // 360도 그리고 끝내라
true // 시계방향으로 그려라
);
context.stroke();
}
var drawNumerals = function () {
var numerals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
angle = 0,
numeralWidth = 0;
numerals.forEach(function (numeral) {
// x, y 그래프는 1사분면부터 4사분면까지 있다.
// 1사분면 x축을 기점으로 시작하기 때문에 왼쪽과 같이 -3을 해줘야된다.
angle = Math.PI / 6 * (numeral - 3);
// measureText 메서드는 대상 텍스트에 대한 정보(예 : 너비)가 포함된 TextMetrics 객체를 반환한다.
// TextMetrics 객체에서 width 값을 받아온다.
numeralWidth = context.measureText(numeral).width;
context.fillText(
numeral, // text 내용
// text를 그릴 x좌표 - 삼각함수 활용
canvas.width / 2 + Math.cos(angle) * (HAND_RADIUS) - numeralWidth / 2,
// text를 그릴 y좌표 - 삼각함수 활용
canvas.height / 2 + Math.sin(angle) * (HAND_RADIUS) + FONT_HEIGHT / 3
)
})
}
var drawCenter = function () {
context.beginPath();
context.arc(canvas.width/2, canvas.height/2, 5, 0, Math.PI*2, true); // 캔버스 정중앙에 반지름이 5px인 원 그리기
context.fill();
}
var drawHand = function (loc, isHour) {
var angle = (Math.PI*2) * (loc/60) - Math.PI/2,
handRadius = isHour ? RADIUS - HAND_TRUNCATION - HOUR_HAND_TRUNCATION : RADIUS - HAND_TRUNCATION;
context.moveTo(canvas.width/2, canvas.height/2);
context.lineTo(
canvas.width/2 + Math.cos(angle)*handRadius,
canvas.height/2 + Math.sin(angle)*handRadius
)
context.stroke()
}
var drawHands = function () {
var date = new Date,
hour = date.getHours();
hour = hour > 12 ? hour - 12 : hour;
// 3번째 인자는 뭘뜻하는걸까?
// 위의 drawHand 함수엔 3번째 인자가 하는 역할이 없는데..?
drawHand(hour*5 + (date.getMinutes()/60)*5, true, 0.5);
drawHand(date.getMinutes(), false, 0.5);
drawHand(date.getSeconds(), false, 0.2);
}
var drawClock = function () {
context.clearRect(0, 0, canvas.width, canvas.height);
drawCircle();
drawCenter();
drawHands();
drawNumerals();
}
// 초기화
context.font = FONT_HEIGHT + 'px Arial';
loop = setInterval(drawClock, 1000);