![[React] canvas & x, y좌표 값으로 길 그리기 [React] canvas & x, y좌표 값으로 길 그리기](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
Canvas API
자바스크립트와 HTML의 canvas 엘리먼트를 통해 그래픽을 그릴 수 있게 제공하는 API로서, HTML5의 구성요소이다.
주로 2D 그래픽을 다루는데 사용되고 있다.
비트맵 데이터의 픽셀 하나 하나를 조작할 수 있고 그래픽 처리 성능이 좋은 편이다.
Method
자주 사용되는 canvas의 메소드는 아래와 같다.
메소드 | 기능 |
beginPath() | 새로운 경로(path)를 생성한다. 새 경로를 생성하는 메소드이기 때문에 최초에 호출하지 않아도 된다. |
closePath() | 경로를 닫는다. 마지막 경로에 있는 점과 시작점을 연결한다. |
stroke() | 경로에 선을 그려준다. |
fill() | 경로의 내부를 채운다. |
moveTo() | 아무것도 그리지 않고 시작 위치를 옮긴다. |
lineTo() | 현재 위치에서 특정 위치까지 선을 그린다. |
fillRect() | 시작 좌표와 width, height 값을 이용해 사각형을 그린다. |
fillStyle | fillRect 함수로 그려지는 사각형 안을 채워줄 색상을 지정한다. |
clearRect() | 시작 좌표와 width, height 값을 이용해 그려진 canvas를 지운다. |
strokeStyle | 선의 색상을 설정한다. |
lineCap | 선의 끝 부분의 스타일을 지정한다. ( butt, round, square ) |
lineJoin | 선이 꺾이는 부분의 스타일을 지정한다. ( bevel, round, miter) |
lineWidth | 선의 굵기를 설정한다. |
코드
interface & 임시 좌표 생성
interface PointProps {
x: number;
y: number;
};
const point: PointProps[] = [
{
x: 82,
y: 65,
},
{
x: 105,
y: 65,
},
{
x: 105,
y: 97,
},
{
x: 221,
y: 97,
},
{
x: 221,
y: 120,
},
];
useRef & HTML 코드 작성
import { useRef } from "react";
import styled from "styled-components";
const width = 600;
const height = 600;
const Layout = styled.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;
const Canvas = styled.canvas`
z-index: 1000;
`;
const ParkingImage = styled.img`
position: absolute;
width: ${width}px;
height: ${height}px;
`;
const CanvasContainer = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
return (
<Layout>
<Canvas ref={canvasRef} width={width} height={height} />
<ParkingImage
src={require("이미지경로")}
/>
</Layout>
);
};
export default CanvasContainer;
선 그리기 코드 작성
const canvasRef = useRef<HTMLCanvasElement>(null);
let z = 0;
let i = 0;
const drawLine = () => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
if (ctx) {
ctx.strokeStyle = "red"; // 선 색깔
ctx.lineCap = "square";
ctx.lineJoin = "round"; // 선 끄트머리(?)
ctx.lineWidth = 3; // 선 굵기
if( i >= point.length-1 ) {
i = 0;
ctx.beginPath();
setTimeout(() => {
ctx.clearRect(0, 0, width, height);
drawLine();
}, 1000);
return;
}
if( i === 0 ) {
ctx.beginPath();
ctx.moveTo(point[i].x, point[i].y);
}
const interval = setInterval(() => {
if( point[i+1].x > point[i].x )
const maxX = point[i+1].x - point[i].x;
if( z >= maxX ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
ctx.lineTo(point[i].x + z, point[i].y);
ctx.stroke();
z += 1;
} else if( point[i].x > point[i+1].x ) {
const maxX = point[i].x - point[i+1].x;
if( z >= maxX ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
ctx.lineTo(point[i].x - z, point[i].y);
ctx.stroke();
z += 1;
} else if( point[i+1].y > point[i].y ) {
const maxY = point[i+1].y - point[i].y;
ctx.lineTo(point[i].x, point[i].y + z);
ctx.stroke();
if( z >= maxY ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
z += 1;
} else if( point[i].y > point[i+1].y) {
const maxY = point[i].y - point[i+1].y;
ctx.lineTo(point[i].x, point[i].y - z);
ctx.stroke();
if( z >= maxY ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
z += 1;
}
}, 10);
}
};
useEffect(() => {
drawLine();
}, []);
코드 설명을 간단하게 해보면,
1. beginPath()로 새로운 선을 그린다고 선언한 다음 moveTo로 point 배열의 index에 해당하는 x, y 좌표로 이동한다.
2. setInterval 함수를 사용해서 40ms마다 좌표를 2씩 증가시켜서 선이 움직이는 것처럼 애니메이션 효과를 준다.
3. 이동한 좌표와 다음 index의 x, y 좌표 값을 비교해서 이동 방향을 정한다.
4. point 배열 사이즈 -1 만큼 함수가 실행되면 1초 후 canvas를 클리어하고 다시 drawLine 함수를 호출한다.
전체 코드
import { useEffect, useRef } from "react";
import styled from "styled-components";
const width = 600;
const height = 600;
const Layout = styled.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;
const Canvas = styled.canvas`
z-index: 1000;
`;
const Image = styled.img`
position: absolute;
width: ${width}px;
height: ${height}px;
`;
interface PointProps {
x: number;
y: number;
};
const point: PointProps[] = [
{
x: 82,
y: 65,
},
{
x: 105,
y: 65,
},
{
x: 105,
y: 97,
},
{
x: 221,
y: 97,
},
{
x: 221,
y: 120,
},
];
const CanvasContainer = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
let z = 0;
let i = 0;
const drawLine = () => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
if (ctx) {
ctx.strokeStyle = "red";
ctx.lineCap = "square";
ctx.lineJoin = "round";
ctx.lineWidth = 3;
if( i >= point.length-1 ) {
i = 0;
ctx.beginPath();
setTimeout(() => {
ctx.clearRect(0, 0, width, height);
drawLine();
}, 1000);
return;
}
if( i === 0 ) {
ctx.beginPath();
ctx.moveTo(point[i].x, point[i].y);
}
const interval = setInterval(() => {
if( point[i+1].x > point[i].x )
const maxX = point[i+1].x - point[i].x;
if( z >= maxX ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
ctx.lineTo(point[i].x + z, point[i].y);
ctx.stroke();
z += 1;
} else if( point[i].x > point[i+1].x ) {
const maxX = point[i].x - point[i+1].x;
if( z >= maxX ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
ctx.lineTo(point[i].x - z, point[i].y);
ctx.stroke();
z += 1;
} else if( point[i+1].y > point[i].y ) {
const maxY = point[i+1].y - point[i].y;
ctx.lineTo(point[i].x, point[i].y + z);
ctx.stroke();
if( z >= maxY ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
z += 1;
} else if( point[i].y > point[i+1].y) {
const maxY = point[i].y - point[i+1].y;
ctx.lineTo(point[i].x, point[i].y - z);
ctx.stroke();
if( z >= maxY ) {
z = 0;
i++;
clearInterval(interval);
drawLine();
}
z += 1;
}
}, 10);
}
};
useEffect(() => {
drawLine();
}, []);
return (
<Layout>
<Canvas ref={canvasRef} width={width} height={height} />
<Image
src={require("이미지경로")}
/>
</Layout>
);
};
export default CanvasContainer;
사용 라이브러리
canvas API(설치x), styled-components
동작 화면
![[React] canvas & x, y좌표 값으로 길 그리기 - 동작 화면 [React] canvas & x, y좌표 값으로 길 그리기 - 동작 화면](https://blog.kakaocdn.net/dn/n2tqM/btsA4dCrIkW/ce7DkEQ2KWTVVsslTBJerK/img.gif)
참고 사이트
https://nookpi.tistory.com/133
Canvas API
사내 세미나에서 진행한 Canvas api 글인데 블로그에도 올려둡니다~ Canvas api란? Canvas API는 javascript와 Html canvas 엘리먼트를 통해 그래픽을 그릴 수 있는 수단을 제공하는 api로, html5의 구성요소입니...
nookpi.tistory.com
https://developer.mozilla.org/ko/docs/Web/API/Canvas_API
Canvas API - Web API | MDN
Canvas API는 JavaScript와 HTML <canvas> 엘리먼트를 통해 그래픽을 그리기위한 수단을 제공합니다. 무엇보다도 애니메이션, 게임 그래픽, 데이터 시각화, 사진 조작 및 실시간 비디오 처리를 위해 사용...
developer.mozilla.org
'🖥️Frontend > React' 카테고리의 다른 글
[React] 지정한 시간 마다 백그라운드 이미지 변경하기 (with TypeScript) (0) | 2024.03.29 |
---|---|
[React] Vite를 사용해서 React 프로젝트 생성 및 실행 (0) | 2024.02.07 |
[React] RTK & TypeScript (1) | 2023.11.20 |
[React] zustand (0) | 2023.11.18 |
[React] Redux & RTK (0) | 2023.11.17 |
댓글