React

리액트와 캔버스 호환

Asset Type
File Type
When to use
Reference
Created by
Created time
2022/03/13 14:49
Last edited time
2022/03/13 15:53
당신과 나의 미래가 React 앱에서 캔버스 요소를 설정하는 시간을 절약할 수 있도록, HTML 캔버스를 React 후크와 함께 사용하는 방법에 대한 최종 버전을 공유하겠습니다.

1단계: 캔버스 요소 렌더링

// src/components/Canvas.js const Canvas = () => { return ( <canvas width="100" height="100" /> ) }; export default Canvas;
TypeScript
복사
width및 height속성은 캔버스 요소에 의해 생성된 이미지에 대해
이미지 해상도와 종횡비(image resolution and the aspect ratio)라는 두 가지를 결정합니다 .

이미지 해상도 Image resolution

이미지에는 100 x 100 픽셀이 있습니다. 이 경우 이미지 너비의 1/100보다 얇은 선을 그리면 하위 픽셀 렌더링으로 끝나므로 성능상의 이유로 인해 이를 피해야 합니다(MDN 기여자 2019b 참조). 가장 얇은 선이 예를 들어 이미지 너비의 1/200이면 너비="200"을 설정해야 합니다.

종횡비 Aspect ratio

위의 예에서는 영상의 가로 세로 비율을 1:1(즉, 정사각형)로 정의합니다.
너비 및 높이 속성을 지정하지 못한 경우(HTML 캔버스의 많은 문서처럼), 기본 가로 세로 비율은 2:1(너비 300px 및 높이 150px)이 적용됩니다.
CSS로 스타일을 지정하는 방법에 따라 이미지가 늘어날 수 있습니다( MDN Contributors 2019a 참조 ). 
Corey의 (2019) - React 후크를 사용하여 캔버스 요소를 렌더링하는 방법에 대한 유용한 기사는 width및 height속성을 지정하지 않아 이 함정에 빠진 것으로 보입니다.
지금까지는 React와 아무 관련이 없습니다. HTML 캔버스를 사용할 때마다 width및 height속성을 설정해야 합니다.

2단계: 캔버스 요소 참조

<canvas> 요소로 이미지를 그리려면 먼저 자바스크립트에서 참조해야 합니다. HTML 캔버스(예: MDN Contributors 2019a )에 대한 소개 튜토리얼에서는 document.getElementById(id)를 사용하도록 안내합니다. 여기서 id는 캔버스 요소의 id 속성 값입니다.
그러나 리액트에서는 useRef 훅을 사용하는 것이 좋습니다(그 이유는 Farmer 2018 참조).
useRef()를 가리키는 변수를 작성한 후 이 변수를 캔버스 요소의 ref 특성 값으로 사용합니다.
// src/components/Canvas.js const Canvas = () => { const canvas = React.useRef(); // ADDED return ( <canvas ref={canvas} // ADDED width="100" height="100" /> ) }; export default Canvas;
TypeScript
복사
이러한 방식으로 캔버스 요소가 화면에 렌더링되면, JavaScript 코드에서는 canvas.current라고 할 수 있습니다.
자세한 내용은 React(2020a) 를 참조하세요.

3단계: 캔버스 컨텍스트 만들기

캔버스 요소에 이미지를 그리려면 CanvasRenderingContext2D 객체를 작성해야 합니다(종종 코드에서 context또는 ctx와 같은 변수 이름 할당).
이 단계는 HTML 캔버스를 리액트와 함께 사용할 때 가장 까다로운 부분입니다. 해결책은 useEffect hook입니다
// src/components/Canvas.js const Canvas = () => { const canvas = useRef(); // ADDED useEffect(() => { const context = canvas.current.getContext('2d'); }); return ( <canvas ref={canvas} width="100" height="100" /> ) }; export default Canvas;
TypeScript
복사
이전 단계에서 설명한 바와 같이 canvas.current는 위의 코드에 있는 <canvas> 요소를 가리킨다.
하지만 리액트가 실제로 캔버스 요소를 화면에 렌더링하기 전까지는 null입니다. 리액트가 구성 요소를 렌더링한 후 코드 세트를 실행하려면 useEffect hook으로 묶어야 합니다(리액트 구성 요소 수명 주기 동안 useEffect 코드 블록이 실행되는 시점은 West 2019 참조).
따라서 코드 블록 내에서 canvas.current<canvas> 요소를 참조한다.
Corey(2019) , Nanda(2020) , van Gilst(2019) 에게 배운 기술 입니다.

4단계: 이미지 그리기

이제 context객체의 다양한 방법으로 이미지를 그릴 준비가 되었습니다( MDN Contributors 2020 참조 ).
그러나 지금까지 작성한 코드를 재사용하려면 이미지를 그리는 코드와 분리하는 것이 가장 좋습니다. 그래서 우리는 Canvas 컴포넌트에 Prop으로 이미지를 그리는 함수를 전달합니다 (이 아이디어는 Nanda 2020 에서 빌렸습니다 ).
// src/components/Canvas.js import PropTypes from 'prop-types'; // ADDED const Canvas = ( {draw} ) => { // CHANGED const canvas = React.useRef(); useEffect(() => { const context = canvas.current.getContext('2d'); draw(context); // ADDED }); return ( <canvas ref={canvas} width="100" height="100" /> ) }; Canvas.propTypes = { // ADDED draw: PropTypes.func.isRequired, }; export default Canvas;
TypeScript
복사
이 draw()함수는 다른 파일에 정의될 이미지를 그립니다. 다양한 그리기 방법에 접근하기 위해 context를 인수로 받습니다.
Canvas컴포넌트가 이제 props를 사용하므로 각 prop의 데이터 유형을 명시적으로 추가 합니다 PropTypesReact 2020b 참조 ).

5단계: 구성 요소를 재사용 가능하게 만들기

이제 이 Canvas 컴포넌트를 재사용하려면 해당 구성 요소의 widthheight 속성을 하드 코딩하지 마십시오. 이미지마다 해상도와 가로 세로 비율이 다릅니다.
따라서 이 두 값을 추가 props로 변환합니다.
// src/components/Canvas.js import PropTypes from 'prop-types'; const Canvas = ( {draw, height, width} ) => { // CHANGED const canvas = React.useRef(); useEffect(() => { const context = canvas.current.getContext('2d'); draw(context); }); return ( <canvas ref={canvas} width={width} // CHANGED height={height} // CHANGED /> ) } Canvas.propTypes = { // ADDED draw: PropTypes.func.isRequired, height: PropTypes.number.isRequired, // ADDED width: PropTypes.number.isRequired, // ADDED }; export default Canvas;
TypeScript
복사
사용의 한 가지 이점은 를 PropTypes추가 .isRequired하면 prop 값 설정을 잊어버린 경우 콘솔에 경고가 표시된다는 것입니다. 위에서 언급했듯이(1단계 참조) width및 height속성은 성능과 이미지 왜곡 방지를 위해 가장 잘 지정됩니다. 위의 코드를 사용하면 해당 값을 지정하는 것을 잊었을 때 경고가 표시됩니다.

6단계: 캔버스 구성 요소 렌더링

마지막으로 parent 컴포넌트에서 draw() 함수를 지정하여 Canvas 컴포넌트를 렌더링합니다.
// src/App.js import Canvas from './components/Canvas'; // Change the path according to the directory structure of your project const draw = context => { // Insert your code to draw an image }; function App() { return ( <Canvas draw={draw} height={100} width={100} /> ); } export default App;
TypeScript
복사