-
Notifications
You must be signed in to change notification settings - Fork 1
DOM을 이미지로 저장하기
juhyojeong edited this page Aug 4, 2024
·
1 revision
캐스퍼 봇 카드 컴포넌트를 이미지로 저장하는 로직을 구현해야했다. 그래서 DOM을 이미지로 저장하는 라이브러리들을 찾아보았다.
HTML 요소를 캔버스로 렌더링하고 이미지로 변환할 수 있게 해준다
import React, { useRef } from 'react';
import html2canvas from 'html2canvas';
const App = () => {
const componentRef = useRef(null);
const handleSaveImage = () => {
if (componentRef.current) {
html2canvas(componentRef.current).then((canvas) => {
const link = document.createElement('a');
link.download = 'component.png';
link.href = canvas.toDataURL();
link.click();
});
}
};
return (
<div>
<div ref={componentRef} className="component-to-save">
<h1>This is the component to save as an image</h1>
</div>
<button onClick={handleSaveImage}>Save as Image</button>
</div>
);
}
DOM 요소를 이미지로 변환하는 라이브러리이다.
import React, { useRef } from 'react';
import domtoimage from 'dom-to-image';
const App = () => {
const componentRef = useRef(null);
const handleSaveImage = () => {
if (componentRef.current) {
domtoimage.toPng(componentRef.current)
.then((dataUrl) => {
const link = document.createElement('a');
link.download = 'component.png';
link.href = dataUrl;
link.click();
})
.catch((error) => {
console.error('Failed to save image:', error);
});
}
};
return (
<div>
<div ref={componentRef} className="component-to-save">
<h1>This is the component to save as an image</h1>
</div>
<button onClick={handleSaveImage}>Save as Image</button>
</div>
);
};
export default App;
html2canvas와 dom-to-image는 내부 동작도 유사했다. DOM을 캔버스에 그리고 캔버스의 이미지 데이터를 toDataURL
를 사용해서 데이터 URL로 만든다. 이 데이터 URL을 기반으로 a 링크로 다운로드 할 수 있다.
dom-to-image에서 dataURL을 반환하는 방식)
function draw(domNode, options) {
return toSvg(domNode, options)
.then(util.makeImage)
.then(util.delay(100))
.then(function (image) {
var canvas = newCanvas(domNode);
canvas.getContext('2d').drawImage(image, 0, 0);
return canvas;
});
function newCanvas(domNode) {
var canvas = document.createElement('canvas');
canvas.width = options.width || util.width(domNode);
canvas.height = options.height || util.height(domNode);
if (options.bgcolor) {
var ctx = canvas.getContext('2d');
ctx.fillStyle = options.bgcolor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
return canvas;
}
}
function toPng(node, options) {
return draw(node, options || {})
.then(function (canvas) {
return canvas.toDataURL();
});
}
API도 매우 유사하고 둘 다 이미지 추출은 잘 되길래 어떤 라이브러리를 사용해도 크게 상관 없겠다 싶었는데, html2canvas(201.9k)보다 dom-to-image(9.8k)가 번들 사이즈가 훨씬 작았기 때문에 dom-to-image 라이브러리를 사용하게 됐다.
- 페이지가 렌더링 된 후 스크롤을 최상단으로 올리기
- DOM을 이미지로 저장하기
- Context API에서 불필요한 리렌더링을 줄이는 방법
- 무한 Transition 애니메이션
- Github Action 워크플로우 정의하기
- 무한 Transition 애니메이션 최적화하기
- 무한 Transition 애니메이션 최적화하기 2
- 무한 Transition 애니메이션 최적화하기 3
- fetch timeout 구현하기
- ErrorBoundary 구현하기
- 뒤로가기 confirm 로직 구현하기
- 선착순 밸런스 게임 상태 관리
- Modal 내부 컴포넌트에서 무한 스크롤이 제대로 동작 안되는 문제
- useToggleContents 훅 기본값 설정 및 조건부 사용법
- 폰트 굵기 적용 이슈
- SVG 내부 stroke 속성 값 제어를 위한 SVGIcon Util 함수 및 SVGR 사용 과정
- tailwindCSS의 @apply를 cva로 바꾸기
- 스크롤 내려갈 때 해당 섹션의 요소들 인터렉션 동작
- 공통 컴포넌트 내부에 애니메이션을 넣는 것에 대한 고민
- 특정 컴포넌트 위치에서 헤더 스타일 다르게 적용하는 방법
- 스크롤 거꾸로 올릴 때 IntersectionObserver가 뷰포트 감지 못하는 현상
- 선착순 밸런스 게임 최종 결과 계산에 대한 고민 (08.14)
- 프로그래스바 공통 컴포넌트로 분리
- (08.23 기준) 선착순 서버 시간 연동 문제
- 게임 종료된 상태에서 사용자 게임 참여 여부에 따른 FinalResult 분기 처리
- FinalResult 컴포넌트의 “당신의 선택” 카테고리 설정 이슈
- 게임 접속 시 게임 현재 진행 상태 초기화 및 카운트 다운 설정
- 선착순 밸런스 게임 UX 개선