시작하기
@newtil/drawing 은 캡처(스크린샷) 위에 화살표·상자·글자를 얹는 그림판 팝업이다. 함수 하나를 부르면 팝업이 뜨고, 사용자가 완료하면 PNG(독자용) 와 JSON(재편집용) 을 함께 돌려준다.
- 프레임워크 없음, 순수 DOM. 자기 shadow root 에 떠서 호스트 스타일과 섞이지 않는다.
- 브라우저 전용이다(
document·canvas를 쓴다). SSR 환경에서는 클라이언트에서만 import 한다.
설치
bash
npm install @newtil/drawingESM(import)·CJS(require) 둘 다 제공하고 타입 선언이 들어 있다. CSS 를 따로 불러올 필요 없다 — 스타일은 shadow root 안에 주입된다.
최소 예시
ts
import { openDrawing } from "@newtil/drawing";
const r = await openDrawing({ background: file }); // { data, png } | null(취소)
const r2 = await openDrawing({ initial: r.data }); // 도형 살아 있는 채로 다시 고치기openDrawing 은 Promise<OpenResult | null> 을 돌려준다. 팝업이 닫힐 때까지 기다린다.
여는 방법 세 가지
ts
// 1. 빈 판(800×450)
await openDrawing();
// 2. 캡처를 배경으로 — File/Blob 또는 같은 출처 이미지 주소
await openDrawing({ background: file });
await openDrawing({ background: "/uploads/shot.png" });
// 3. 이전 결과(JSON)로 다시 열기 — 도형이 그대로 살아 있다
await openDrawing({ initial: savedDrawing });background는 긴 변이 1600px 을 넘으면 줄여서 data URL 로 굽는다. 판 크기(width·height)는 그 이미지 크기가 된다.initial이 있으면background는 무시된다.- 배경 로드에 실패하면(이미지가 아니거나 교차 출처 등) 배경 없이 빈 판으로 열린다.
- 배경 없이 열었더라도 팝업 안에서 캡처를 붙여넣거나(⌘V / Ctrl+V) "배경 이미지…" 버튼으로 고를 수 있다.
결과 처리
ts
const r = await openDrawing({ background: file });
if (!r) return; // 취소
r.png; // Blob("image/png") — 문서에 넣을 결과물
r.data; // Drawing — 도형이 살아 있는 JSON. 다음에 initial 로 넘기면 다시 고칠 수 있다
r.saved; // save 훅이 돌려준 값(주소 등). 훅이 없으면 undefinedPNG 는 보여주는 데 쓰고, data 는 PNG 옆에 곁파일로 저장해 둔다. data 는 배경까지 data URL 로 품고 있어 어디에 두든 자기 완결적이다. 자세한 구조는 데이터 형식 참고.
PNG 를 바로 <img> 에 넣으려면:
ts
import { blobToDataURL } from "@newtil/drawing";
img.src = await blobToDataURL(r.png); // 또는 URL.createObjectURL(r.png)저장까지 팝업 안에서
save 훅을 주면 "완료" 를 눌렀을 때 팝업 안에서 호출한다. 서버에 올리고 문서에 넣을 주소를 돌려주면 그 값이 r.saved 에 실린다. 훅이 던지면 팝업은 닫히지 않고 이유를 보인다.
ts
const r = await openDrawing({
background: file,
save: async (png, data) => {
const url = await upload(png, data); // 실패하면 throw — 팝업이 열린 채 이유를 보인다
return url;
},
});계약과 실패 시 동작은 저장 훅 참고.
취소
다음 경우 null 이 돌아온다.
- "취소" 버튼
- 어두운 배경(팝업 바깥) 클릭
Esc— 선택된 도형이 있으면 먼저 선택만 풀고, 없으면 취소
한 번이라도 그리거나 고친 뒤라면 "그린 것을 버릴까요?" 확인을 묻는다(window.confirm). 저장 중(save 훅 진행 중)에는 취소되지 않는다.
그 밖의 옵션
ts
await openDrawing({
background: file,
notice: "도형 데이터 없이 PNG 만으로 열었습니다.", // 열 때 6초간 보이는 안내
lang: "en", // 메시지 언어. 기본은 document.documentElement.lang
messages: { done: "Insert" }, // 메시지 일부 덮어쓰기
mount: container, // 팝업을 붙일 자리. 기본 document.body
});전체 목록은 API 의 OpenOptions 참고.