Skip to content

canvas document.querySelector 이슈

Jin edited this page Dec 2, 2020 · 2 revisions

그림판, 배경화면 변경과 같은 기능을 구현하기 위해서 canvas를 사용할 필요가 있었는데 이에 대한 고민을 적어보려고 합니다.

  1. html -> canvas로 변환
  • 기존의 html을 선택해서 canvas로 변환하는 부분이 있어야 했고, html2canvas라는 라이브러리를 설치해야 했습니다.
  1. 설치과정
npm install @type2/html2canvas html2canvas
  1. 전체 로직
// div 영역 선택
const mathquillSection = document.querySelector(
     '.kkOleo'
   ) as HTMLCanvasElement;

// 이 부분이 핵심입니다. html 영역을 canvas로 바꿔주는 영역입니다. 단 promise를 반환해서 async await을 적용했습니다.
   const canvas = await html2canvas(mathquillSection);

// 캔버스의 내용을 문자열로 바꿔주는 부분입니다. 
// 이 부분은 이미지 MIME 타입과 인코딩 방법 그리고 인코딩 된 이미지 데이터 문자열이 포함됩니다.
// 저는 애니메이션을 포함하기 위해서 image/gif로 설정해주었습니다.
   const imageUrl = canvas.toDataURL('image/gif');
  
// 클릭 이벤트를 주기 위해서 a태그를 생성하였습니다.
   const aTag = document.createElement('a');

// aTag를 body에 추가하였습니다.
   document.body.appendChild(aTag);

// 수식 저장.gif 파일을 클릭하면 다운로드 가능하도록 구현합니다.
   aTag.download = '수식 저장.gif';

// href을 설정합니다.
   aTag.href = imageUrl;

// 클릭 이벤트 설정합니다.
   aTag.click();

// aTag를 다시 지워줍니다.
   document.body.removeChild(aTag);

이렇게 하면 이미지 저장이 가능합니다.

스크린샷 2020-12-02 오후 3 34 53 스크린샷 2020-12-02 오후 3 35 05

참고 MIME 타입에 대한 설명

새로운 접근

  1. 위의 방식으로 진행하게 되면 문제점이 발생하게 된다.
  • document.querySelector로 클래스를 지정할 경우 리액트에 의해서 변환된 클래스 이름으로 인해서 에러가 발생합니다.
  • 이러한 에러를 해결하는 방법을 여러가지 생각해보았고, 그 중에서 좀 괜찮다고 판단했던 방법을 제시하려고 합니다.
  1. useRef와 redux를 이용해서 문제 해결해보기
  • useRef는 컴포넌트 내에서 dom 조작을 할 수 있도록 도와줍니다. 따라서 이 녀석을 이용하면 해결할 수 있을거라는 판단하에 진행하게 되었습니다.
  • useRef는 컴포넌트 내에서만 접근이 가능하기에 Redux를 이용해서 문제를 해결하려고 노력하였습니다.
  1. 새로운 소스
  • useRef를 이용해서 ref의 값을 초기화합니다.
  • dispatch를 이용해서 mathquill 영역을 저장합니다.
  • useSelector를 이용해서 상태값을 가져오고 html2canvas를 통해서 다시 저장해줍니다.
const mainSectionRef = useRef<HTMLDivElement>(null);
 
useEffect(() => {
  dispatch(getMathQuillContainer(mainSectionRef));
}, []);
const { mathQuillContainer } = useSelector(
  (state: RootState) => state.getMathQuillReducer
);
const onClickImageSaveHandler = async () => {
  const mathquillSection = mathQuillContainer.current;

  const canvas = await html2canvas(mathquillSection);

  const imageUrl = canvas.toDataURL('image/gif');

  const aTag = document.createElement('a');

  document.body.appendChild(aTag);

  aTag.download = '수식 저장.gif';

  aTag.href = imageUrl;

  aTag.click();

  document.body.removeChild(aTag);
};

🤝 Rules

🤖 개발 진행 공유

🧑‍🏫 학습 정리

📖 Document

😄데일리 스크럼
😄일일 회의록
😄주간 회고록

🗣 피어세션

🔥 트러블 슈팅

Clone this wiki locally