CS
Canvas
juni_shin
2025. 4. 18. 15:29
Canvas란?
- Canvas는 HTML5에서 제공하는 2D 그래픽을 그릴 수 있는 요소입니다. JavaScript를 사용하여 실시간으로 그래픽을 렌더링할 수 있으며, 게임, 애니메이션, 데이터 시각화 등에 주로 사용됩니다.
Canvas 기본 사용법
1. Canvas 요소 생성
<canvas id="myCanvas" width="800" height="600"></canvas>
2. Canvas 컨텍스트 가져오기
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
3. 기본 도형 그리기
- 사각형
// 채워진 사각형
ctx.fillStyle = 'red';
ctx.fillRect(x, y, width, height);
// 테두리만 있는 사각형
ctx.strokeStyle = 'blue';
ctx.strokeRect(x, y, width, height);
- 원
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.fill(); // 채우기
ctx.stroke(); // 테두리
- 선
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
4. 스타일 설정
- 색상
ctx.fillStyle = 'red'; // 채우기 색상
ctx.strokeStyle = 'blue'; // 테두리 색상
- 선 스타일
ctx.lineWidth = 2; // 선 두께
ctx.lineCap = 'round'; // 선 끝 스타일
ctx.lineJoin = 'round'; // 선 연결부 스타일
5. 이미지 그리기
const img = new Image();
img.src = 'image.png';
img.onload = () => {
ctx.drawImage(img, x, y, width, height);
};
6. 애니메이션 구현
- 기본 애니메이션 루프
function animate() {
// 1. 화면 지우기
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2. 그리기 작업
// 3. 다음 프레임 요청
requestAnimationFrame(animate);
}
- 성능 최적화
// 이중 버퍼링
const offscreenCanvas = document.createElement('canvas');
const offscreenCtx = offscreenCanvas.getContext('2d');
// 복잡한 그리기 작업을 오프스크린에서 수행
offscreenCtx.drawImage(...);
// 메인 캔버스에 한 번에 복사
ctx.drawImage(offscreenCanvas, 0, 0);
7. 이벤트 처리
- 마우스 이벤트
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 클릭 위치 처리
});
- 키보드 이벤트
window.addEventListener('keydown', (e) => {
switch(e.key) {
case 'ArrowLeft':
// 왼쪽 이동
break;
case 'ArrowRight':
// 오른쪽 이동
break;
}
});
8. 그리기 기능
- 그라데이션
// 선형 그라데이션
const linearGradient = ctx.createLinearGradient(x1, y1, x2, y2);
linearGradient.addColorStop(0, 'red');
linearGradient.addColorStop(1, 'blue');
ctx.fillStyle = linearGradient;
// 원형 그라데이션
const radialGradient = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
radialGradient.addColorStop(0, 'red');
radialGradient.addColorStop(1, 'blue');
ctx.fillStyle = radialGradient;
- 패턴
const img = new Image();
img.src = 'pattern.png';
img.onload = () => {
const pattern = ctx.createPattern(img, 'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
- 그림자 효과
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
- 클리핑 영역
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.clip(); // 이 영역 밖으로는 그려지지 않음
9. 변환 기능
- 이동
ctx.translate(x, y); // 그리기 시작점 이동
- 회전
ctx.rotate(angle); // 현재 위치 기준 회전
- 크기 조절
ctx.scale(scaleX, scaleY); // 크기 조절
- 변환 행렬
ctx.transform(a, b, c, d, e, f); // 커스텀 변환 행렬 적용
ctx.setTransform(a, b, c, d, e, f); // 현재 변환 행렬 초기화 후 적용
10. 텍스트 그리기
- 기본 텍스트
ctx.font = '30px Arial';
ctx.fillText('Hello World', x, y);
ctx.strokeText('Hello World', x, y);
- 텍스트 정렬
ctx.textAlign = 'center'; // left, right, center, start, end
ctx.textBaseline = 'middle'; // top, hanging, middle, alphabetic, ideographic, bottom
- 텍스트 측정
const metrics = ctx.measureText('Hello World');
console.log(metrics.width); // 텍스트 너비
11. 합성
- 전역 합성 (캔버스에 여러 요소를 그릴 때, 요소들이 서로 어떻게 겹치고 상호작용하는지 정의하는 속성)
// 1. 기본 모드 - 새로운 도형이 기존 도형 위에 그려짐
ctx.globalCompositeOperation = 'source-over';
// 2. 새로운 도형과 기존 도형이 겹치는 부분만 보임
ctx.globalCompositeOperation = 'source-in';
// 3. 새로운 도형이 기존 도형과 겹치지 않는 부분만 보임
ctx.globalCompositeOperation = 'source-out';
// 4. 새로운 도형이 기존 도형 아래에 그려짐
ctx.globalCompositeOperation = 'destination-over';
// 5. 기존 도형과 새로운 도형이 겹치는 부분만 보임
ctx.globalCompositeOperation = 'destination-in';
// 6. 기존 도형에서 새로운 도형과 겹치지 않는 부분만 보임
ctx.globalCompositeOperation = 'destination-out';
// 7. 새로운 도형이 기존 도형 위에 그려지고, 겹치는 부분은 기존 도형이 보임
ctx.globalCompositeOperation = 'source-atop';
// 8. 새로운 도형이 기존 도형 아래에 그려지고, 겹치는 부분은 새로운 도형이 보임
ctx.globalCompositeOperation = 'destination-atop';
// 9. 겹치는 부분의 색상값이 더해짐 (밝아짐)
ctx.globalCompositeOperation = 'lighter';
// 10. 새로운 도형만 보이고 기존 도형은 모두 지워짐
ctx.globalCompositeOperation = 'copy';
// 11. 겹치는 부분이 투명해짐
ctx.globalCompositeOperation = 'xor';
// 12. 색상 곱하기 효과
ctx.globalCompositeOperation = 'multiply';
// 13. 색상 스크린 효과
ctx.globalCompositeOperation = 'screen';
// 14. 오버레이 효과
ctx.globalCompositeOperation = 'overlay';
// 15. 어두운 색상만 보임
ctx.globalCompositeOperation = 'darken';
// 16. 밝은 색상만 보임
ctx.globalCompositeOperation = 'lighten';
// 17. 색상 닷지 효과
ctx.globalCompositeOperation = 'color-dodge';
// 18. 색상 번 효과
ctx.globalCompositeOperation = 'color-burn';
// 19. 하드 라이트 효과
ctx.globalCompositeOperation = 'hard-light';
// 20. 소프트 라이트 효과
ctx.globalCompositeOperation = 'soft-light';
// 21. 차이 효과
ctx.globalCompositeOperation = 'difference';
// 22. 배제 효과
ctx.globalCompositeOperation = 'exclusion';
// 23. 색상 효과
ctx.globalCompositeOperation = 'hue';
// 24. 채도 효과
ctx.globalCompositeOperation = 'saturation';
// 25. 색상 혼합 효과
ctx.globalCompositeOperation = 'color';
// 26. 명도 효과
ctx.globalCompositeOperation = 'luminosity';
- 투명도
ctx.globalAlpha = 0.5; // 0.0 ~ 1.0
12. 이미지 조작
- 이미지 데이터 가져오기
const imageData = ctx.getImageData(x, y, width, height);
- 픽셀 조작
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // R
data[i + 1] = 255 - data[i + 1]; // G
data[i + 2] = 255 - data[i + 2]; // B
// data[i + 3]는 알파 채널
}
ctx.putImageData(imageData, x, y);
13. 성능 최적화
- 애니메이션 최적화 (requestAnimationFrame)
- 브라우저의 렌더링 주기에 맞춰 최적화된 타이밍에 실행됩니다
- setInterval 이나 setTimeout 대신 사용하는 것이 권장됩니다.
- 브라우저가 다음 화면을 그리기 전에 실행할 함수를 예약하는 메서드입니다
function animate() {
// 1. 화면 지우기
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2. 그리기 작업
// 예: 캐릭터 이동, 물체 그리기 등
// 3. 다음 프레임 요청
requestAnimationFrame(animate);
}
// 애니메이션 시작
requestAnimationFrame(animate);