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);