Skip to content

그림판 연동

그림판 자체는 @newtil/drawing 이다. 편집기는 열고 · 넣고 · 고치는 접착부만 가진다(0.10.12, src/plugins/drawing.ts).

어디서 열리나

  • 상단 툴바의 그림판 버튼, 슬래시 /그림판(/drawing) — 빈 판으로 열고 완료하면 이미지로 삽입
  • 문서 속 이미지를 고르면 뜨는 그림 고치기 버튼, 또는 이미지 두 번 클릭 — 도형째 다시 연다 (0.10.13)
  • 그림판은 한 번에 하나만 뜬다. 버튼 연타·더블클릭이 겹쳐도 두 개가 뜨지 않는다

시그니처역할
onDrawingSave({ png: Blob, data: DrawingData, previousSrc: string | null }) => Promise<string>구운 PNG 와 도형 데이터를 저장하고 문서에 넣을 주소를 돌려준다. previousSrc 는 고치던 그림의 주소(새 그림이면 null)
onDrawingLoad(src: string) => Promise<DrawingData | null>이미지 주소에 대한 도형 데이터가 있으면 준다. 없으면 null
js
const drawings = new Map();   // 예시 — 실제로는 서버가 PNG 옆에 JSON 곁파일로 둔다

editor.onDrawingSave = async ({ png, data, previousSrc }) => {
  const form = new FormData();
  form.append("png", png);
  form.append("data", JSON.stringify(data));
  if (previousSrc) form.append("previousSrc", previousSrc);
  const res = await fetch("/api/drawings", { method: "POST", body: form });
  return (await res.json()).url;          // 예: "/upload/drawing-1.png"
};

editor.onDrawingLoad = async (src) => {
  const res = await fetch(`/api/drawings?src=${encodeURIComponent(src)}`);
  return res.ok ? await res.json() : null; // DrawingData | null
};

React 는 onDrawingSave·onDrawingLoad prop, Vue 도 같은 이름의 prop 으로 넘긴다.

훅이 없을 때

  • 저장 훅이 없으면 PNG 를 data URL 로 본문에 넣는다. 도형 데이터는 잃는다 — 다시 열면 그 그림이 배경이 되고 이전 도형은 그림에 박힌 채 남는다
  • 불러오기 훅이 있는데 null 을 주면(또는 던지면) 그 그림을 배경으로 열고 안내(messages.drawingNoDataNotice)를 띄운다
  • 저장 훅이 던지면 그림판이 열린 채 이유를 보인다. 조용히 data URL 로 넘기지 않는다 (0.10.10)

데이터 흐름

[새로 그리기]  툴바·/그림판 → openDrawing({ save })
                 완료 → save(png, data) → onDrawingSave({ png, data, previousSrc: null }) → url
                 → 문서에 image 노드 { src: url, alt: messages.drawingAlt }

[고치기]       이미지 선택 → 그림 고치기 / 두 번 클릭
                 → onDrawingLoad(src) → DrawingData ? openDrawing({ initial }) : openDrawing({ background: src, notice })
                 완료 → onDrawingSave({ png, data, previousSrc: src }) → url
                 → 그 image 노드의 src 를 url 로 교체(선택 유지)

무엇이 저장되나

  • 마크다운에는 ![그림](url) 만 남는다(폭·정렬·테두리를 바꾸면 <img …>). 도형 JSON 은 문서에 들어가지 않는다
  • 도형 데이터(DrawingData)는 호스트가 PNG 옆 곁파일로 맡는다. 형식은 @newtil/drawingDrawing:
ts
interface Drawing {
  version: 1;
  width: number; height: number;   // 판 크기 — 좌표는 항상 이 기준
  background: string | null;       // 배경 캡처(data URL). 없으면 흰 판
  shapes: Shape[];                 // rect · ellipse · line · arrow · arrow2 · pen · highlighter · text · badge
}

DrawingData·DrawingShape 타입은 @newtil/editor 에서 다시 export 된다. 형식은 0.10.7 의 곁파일과 같아 기존 데이터가 그대로 열린다.

언어

그림판 문자열은 편집기의 lang 을 그대로 넘긴다(ko/en). 그림판 자체 문구는 @newtil/drawing 이 가지고, 편집기 messages 로는 접착부 문구(drawing, drawingEdit, drawingAlt, drawingNoDataNotice)만 바꾼다.