때는 3월, 플랜 빙고를 막 배포했을 당시, 한 유저로부터 이런 피드백을 받았다.
나중에 이미지 저장 기능도 있으면 좋을 것 같아요...! 캡쳐도 되지만 이렇게 예쁜 디자인이 주소창이랑 찍히는게 아쉬워서요
유저의 피드백을 잘 기록해뒀다가 안 바쁜 시기인 7월에 드디어 빙고판을 이미지로 저장하는 기능을 만들었다!
(자축하는 의미로 박수👏👏👏)
⚠️ 다만 본격적인 포스팅에 앞서 미리 언급해야할 점이 있다.
Apple 기기에서는 이미지 다운로드 기능이 작동이 안 된다는 점이다.file-saver
를 사용하면 해당 문제가 없어질 줄 알았는데, 이상하게도 해결할 수 없었다.
나는 현재 맥북이 없어서 Apple 기기와 관련된 에러를 확인할 방법이 없다. 그래서 이 버그는 추후에 기회가 되면 고치겠다. (이 점에 관해 아시는 분이 있다면 댓글 환영합니다.💚)
기능을 구현하기 전 고민이 있었다. 이미지의 형태를 어떻게 할지 고민이었다.
그래서 트위터에 투표를 올렸다.
투표 결과 주변 여백이 보이게 이미지를 생성하는 것이 제일 많이 득표를 받았다. 나는 투표 결과대로 진행하기로 했다.
ℹ️ 기술 스택
React.js, Next.js, JavaScript
나는 이 기능을 추가하기 위해 html2canvas
와 file-saver
를 사용했다.
html2canvas
html2canvas
는 javascript 브라우저 화면 캡처 라이브러리이다.
이 라이브러리를 사용하면 캡처할 영역을 지정하고 해당 영역에 관한 스크린샷을 찍을 수 있다.
공식문서: https://html2canvas.hertzen.com/
특징
html2canvas
설치 방법
npm install --save html2canvas
or
yarn add html2canvas
file-saver
file-saver
는 클라이언트에서 파일 저장을 도와주는 라이브러리다.
공식 문서: https://www.npmjs.com/package/file-saver
설치 방법
npm install file-saver --save
or
yarn add file-saver
(추가로, 타입스크립트를 이용하는 경우에는 타입 정의도 다운로드 되어야 한다.)
# Additional typescript definitions
npm install @types/file-saver --save-dev
or
yarn add @types/file-saver -D
지원되는 브라우저
https://www.npmjs.com/package/file-saver#supported-browsers
html2canvas
+ file-saver
활용하여 기능을 구현한 방법useRef
와 div
태그를 사용하여 캡처하고 싶은 영역을 감싸주기.useRef
를 쓴다.import { useRef } from "react";
const divRef = useRef(null);
<div ref={divRef} className={styles.canvasDiv}>
<ShareBoard
bingoData={bingoData}
main={data.main}
title={data.title}
value1={data.value1}
value2={data.value2}
value3={data.value3}
value4={data.value4}
value5={data.value5}
value6={data.value6}
value7={data.value7}
value8={data.value8}
value9={data.value9}
bgColor={data.bgColor}
cubeColor={data.cubeColor}
bingoCount={data.bingoCount}
patternArray={data.patternArray}
/>
</div>
터미널에서 html2canvas
와 file-saver
를 설치.
import
import html2canvas from "html2canvas";
import saveAs from "file-saver";
<button
className={[btnStyles.button, styles.btnColor].join(" ")}
onClick={downloadCanvasDiv}
>
<Image
src={"/download.svg"}
alt={"download an image"}
width={30}
height={30}
/>{" "}
<p>이미지로 저장하기</p>
</button>
const downloadCanvasDiv = async () => {
const div = divRef.current;
if (!div) {
return;
}
try {
const canvas = await html2canvas(div);
canvas.toBlob((blob) => {
if (blob != null) {
saveAs(blob, `${data.title}.png`);
}
});
} catch (error) {
console.error("Error converting div to image:", error);
}
};
이렇게 특정 영역을 캡처하여 이미지로 저장하는 기능을 구현했다.
(아래는 이미지로 저장된 나의 플랜 빙고이다.)
오랜만에 플랜빙고에 기능을 추가해서 뿌듯했다.
다만 Apple 기기에서는 작동이 안 된다는 점이 매우 아쉽다.
언젠가 꼭 고치겠어!
참고 자료
[React] 화면(DOM) 캡쳐 및 저장 기능 구현하기 (feat. html2canvas, file-saver)