셰이더, 메시, 필터의 세계에서 Canvas2D는 그리 흥미롭지 않을 수 있습니다. 하지만 그래야 합니다.
웹페이지의 30~40% 에는 <canvas>
요소가 있고 모든 캔버스의 98% 는 Canvas2D 렌더링 컨텍스트를 사용합니다. 자동차, 냉장고, 우주에서도 Canvas2D를 사용할 수 있습니다.
최신 2D 그리기와 관련하여 API는 약간 뒤처져 있습니다. 다행히 Google은 CSS를 따라잡고 인체공학을 간소화하고 성능을 개선하기 위해 Canvas2D에 새로운 기능을 구현하기 위해 노력했습니다.
파트 1: CSS 따라잡기
CSS에는 Canvas2D에서 누락된 몇 가지 그리기 명령어가 있습니다. 새 API에는 가장 요청이 많았던 몇 가지 기능이 추가되었습니다.
둥근 직사각형
원형 직사각형: 인터넷, 컴퓨팅, 문명의 초석입니다.
둥근 직사각형은 버튼, 채팅 풍선, 썸네일, 말풍선 등 다양한 용도로 매우 유용합니다. Canvas2D에서 원형 직사각형을 만드는 것은 항상 가능했지만 약간 지저분했습니다.
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'magenta';
const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;
ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();
간단하고 둥근 직사각형을 만들기 위해 필요한 모든 요소입니다.
새 API에는 roundRect()
메서드가 있습니다.
ctx.roundRect(upper, left, width, height, borderRadius);
위의 함수를 다음으로 완전히 대체할 수 있습니다.
ctx.roundRect(10, 10, 200, 100, 20);
ctx.roundRect()
메서드는 최대 4개의 숫자로 구성된 borderRadius
인수 배열도 사용합니다. 이 반지름은 CSS와 동일한 방식으로 원형 직사각형의 네 모서리를 제어합니다. 예를 들면 다음과 같습니다.
ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);
원뿔 그라데이션
선형 그래디언트를 확인했습니다.
const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);
방사형 그래디언트:
const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');
ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
멋진 원뿔형 그라데이션은 어떨까요?
const grad = ctx.createConicGradient(0, 100, 100);
grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);
텍스트 수식어
Canvas2D의 텍스트 렌더링 기능은 매우 뒤떨어져 있습니다. Chrome에 Canvas2D 텍스트 렌더링에 몇 가지 새로운 속성이 추가되었습니다.
- ctx.letterSpacing
- ctx.wordSpacing
- ctx.fontVariant
- ctx.fontKerning
- ctx.fontStretch)
- ctx.textDecoration
- ctx.textUnderlinePosition
- ctx.textRendering
이러한 속성은 모두 이름이 동일한 CSS 속성과 일치합니다.
2단계: 인체공학적 조정
이전에는 Canvas2D로 일부 작업을 할 수 있었지만 구현하기가 불필요하게 복잡했습니다. 다음은 Canvas2D를 사용하려는 JavaScript 개발자를 위한 몇 가지 편의성 개선사항입니다.
컨텍스트 재설정
캔버스 지우기를 설명하기 위해 레트로 패턴을 그리는 함수를 작성했습니다.
draw90sPattern();
좋습니다. 이제 패턴을 완성했으므로 캔버스를 지우고 다른 것을 그려 보겠습니다.
잠깐, 캔버스를 다시 지우려면 어떻게 해야 하나요? 와우! 물론 ctx.clearRect()
입니다.
ctx.clearRect(0, 0, canvas.width, canvas.height);
어… 안 되네요. 와우! 먼저 변환을 재설정해야 합니다.
ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
그렇다면 멋진 빈 캔버스 이제 멋진 가로선을 그려 보겠습니다.
ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();
으르르! 오답입니다. ❯ 추가 선이 여기에 무엇인가요? 또한 분홍색인 이유는 무엇인가요? 좋습니다. StackOverflow를 확인해 보겠습니다.
canvas.width = canvas.width;
왜 이렇게 어리석은 걸까요? 왜 이렇게 어려운가요?
이제는 더 이상 그렇지 않습니다. 이 새로운 API를 통해 간단하고 우아하며 아름다운 혁신적인 기능을 사용할 수 있습니다.
ctx.reset();
오래 기다리게 해드려 죄송합니다.
필터
SVG 필터는 그 자체만으로는 완전한 필터입니다. SVG 필터를 처음 사용하는 경우 SVG 필터의 기술과 그 멋진 이유를 읽어보세요. 이 도움말에서는 SVG 필터의 놀라운 잠재력을 보여줍니다.
Canvas2D에서 SVG 스타일 필터를 이미 사용할 수 있습니다. 페이지의 다른 SVG 필터 요소를 가리키는 URL로 필터를 전달하기만 하면 됩니다.
<svg>
<defs>
<filter id="svgFilter">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
<feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
<feColorMatrix type="hueRotate" values="90" />
</filter>
</defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);
이로 인해 패턴이 상당히 흐려집니다.
그러나 위의 작업을 수행하되 JavaScript 내에서 문자열을 사용하고 싶지 않다면 어떻게 해야 할까요? 새 API를 사용하면 이러한 작업이 가능합니다.
ctx.filter = new CanvasFilter([
{ filter: 'gaussianBlur', stdDeviation: 5 },
{
filter: 'convolveMatrix',
kernelMatrix: [
[-3, 0, 0],
[0, 0.5, 0],
[0, 0, 3],
],
},
{ filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);
식은 죽 먹기 여기에 있는 데모에서 직접 사용해 보고 매개변수를 사용해 보세요.
3단계: 성능 개선
또한, 새 Canvas2D API로 가능한 경우 성능을 개선하고자 했습니다. 개발자가 웹사이트를 더 세부적으로 제어하고 최대한 매끄러운 프레임 속도를 허용할 수 있도록 다음과 같은 몇 가지 기능을 추가했습니다.
자주 읽음
getImageData()
를 사용하여 캔버스에서 픽셀 데이터를 다시 읽습니다. 매우 느릴 수 있습니다. 이 새로운 API를 사용하면 생성 효과와 같이 다시 읽기 위해 캔버스를 명시적으로 표시할 수 있습니다.
이렇게 하면 내부적으로 항목을 최적화하고 다양한 사용 사례에 맞게 캔버스의 속도를 빠르게 유지할 수 있습니다. 이 기능은 Firefox에 한동안 제공되어 왔으며 드디어 캔버스 사양에 포함될 예정입니다.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
컨텍스트 손실
슬픈 탭을 다시 행복하게 만들어 보세요. 클라이언트의 GPU 메모리가 부족하거나 캔버스에 다른 문제가 발생하면 이제 콜백을 수신하고 필요에 따라 다시 그릴 수 있습니다.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);
캔버스 컨텍스트와 손실에 관한 자세한 내용은 WhatWG의 위키에서 유용한 설명을 참고하세요.
결론
Canvas2D를 처음 사용하거나 몇 년 동안 사용해 온 사용자 또는 몇 년 동안 사용하지 않았던 사용자 등 Canvas2D를 한 번 더 사용해 보라고 말씀드리고자 합니다. 항상 옆에 있는 API입니다.