Programming

Open annotation 렌더링 - JSON-LD 를 문서에 출력하는 방법

IT오이시이 2025. 5. 1. 13:01
728x90

 

Open annotation JSON-LD 형식의 주석을 읽고 PDF 문서에 출력(렌더링)하는 방법.

이 과정은 다음과 같이 진행됩니다:

  1. JSON-LD 주석 데이터 저장하고 읽기
  2. 웹페이지에서 JSON-LD 주석 데이터 가져오기와서 출력하기
  3. PDF.js를 이용해 PDF 문서를 렌더링하기
  4. 주석 데이터를 읽어 특정 위치에 출력하기

📌 1.Open annotation JSON 형식으로 저장

Open Annotation은 구조화된 데이터를 JSON 형식으로 표현하고 저장 할 수 있습니다:

{
  "annotation": {
    "id": "12345",
    "body": "이것은 주석 내용입니다.",
    "target": "https://example.com/document",
    "creator": "agileBus",
    "created": "2025-05-05T22:08:00Z"
  }
}

JSON 문서는 주석의 ID, 내용, 대상 URL, 작성자, 생성 날짜 등의 정보를 포함합니다.

JSON 파일로 저장 : Python을 사용하여 JSON 데이터를 파일로 저장할 수 있습니다.

import json

annotation_data = {
    "annotation": {
        "id": "12345",
        "body": "이것은 주석 내용입니다.",
        "target": "https://example.com/document",
        "creator": "agileBus",
        "created": "2025-05-05T22:08:00Z"
    }
}

# JSON 파일로 저장
with open("annotation.json", "w", encoding="utf-8") as file:
    json.dump(annotation_data, file, ensure_ascii=False, indent=4)

JSON 파일에서 데이터 읽기 및 출력 : 저장된 JSON 파일을 읽고 출력 합니다.

# JSON 파일 읽기
with open("annotation.json", "r", encoding="utf-8") as file:
    loaded_data = json.load(file)

# 데이터 출력
print(json.dumps(loaded_data, ensure_ascii=False, indent=4))

다음과 같이 json 파일이 정의 되면 javascript를 이용하여 화면에 출력하는 예시를 작성 할 수 있습니다.


📌 1.Open annotation JSON-LD 주석 데이터 가져오기

JSON-LD 형식의 주석 데이터는 다음과 같은 구조를 가질 수 있습니다:

{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "annotations": [
    {
      "id": "http://example.org/annotations/1",
      "type": "Annotation",
      "body": {
        "type": "TextualBody",
        "value": "이 부분은 중요한 내용입니다.",
        "format": "text/plain"
      },
      "target": {
        "source": "http://example.org/document.pdf",
        "selector": {
          "type": "FragmentSelector",
          "value": "page=2&xywh=100,200,300,400"
        }
      },
      "creator": "agileBus",
      "created": "2025-05-05T22:08:00Z"
    },
    {
      "id": "http://example.org/annotations/2",
      "type": "Annotation",
      "body": {
        "type": "TextualBody",
        "value": "이 부분도 참고하세요.",
        "format": "text/plain"
      },
      "target": {
        "source": "http://example.org/document.pdf",
        "selector": {
          "type": "FragmentSelector",
          "value": "page=3&xywh=150,250,350,450"
        }
      },
      "creator": "agileBus",
      "created": "2025-05-05T22:10:00Z"
    }
  ]
}

이 데이터에서 target.selector.value 값을 이용하여 주석이 출력될 위치를 지정할 수 있습니다.


📌 2. PDF.js를 이용한 PDF 렌더링

PDF.js 라이브러리를 사용하여 PDF 문서를 브라우저에 렌더링합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>PDF Annotation Display</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.12.313/pdf.min.js"></script>
    <style>
        #pdf-container { position: relative; width: 800px; height: 600px; border: 1px solid #ccc; }
        .annotation { position: absolute; background: yellow; padding: 5px; border-radius: 4px; cursor: pointer; }
    </style>
</head>
<body>
    <h2>PDF 주석 출력</h2>
    <div id="pdf-container"></div>

    <script>
        const container = document.getElementById("pdf-container");
        const jsonLdUrl = "http://example.org/annotations/1"; // 주석 JSON-LD URL

        fetch(jsonLdUrl)
            .then(response => response.json())
            .then(annotation => {
                const pdfUrl = annotation.target.source;
                // renderPDF(pdfUrl, annotation);
                const annotations = data.annotations;
                annotations.forEach(annotation => {
                     renderPDF(annotation.target.source, annotation);
                 });
            });

        function renderPDF(url, annotation) {
            pdfjsLib.getDocument(url).promise.then(pdf => {
                pdf.getPage(2).then(page => { // 주석이 있는 페이지
                    const scale = 1.5;
                    const viewport = page.getViewport({ scale });

                    const canvas = document.createElement("canvas");
                    container.innerHTML = "";
                    container.appendChild(canvas);
                    canvas.width = viewport.width;
                    canvas.height = viewport.height;

                    const ctx = canvas.getContext("2d");
                    const renderContext = { canvasContext: ctx, viewport };
                    page.render(renderContext).promise.then(() => {
                        addAnnotation(annotation, viewport);
                    });
                });
            });
        }

        function addAnnotation(annotation, viewport) {
            const selector = annotation.target.selector.value.split("=")[1];
            const [x, y, width, height] = selector.split(",").map(Number);

            const annotationDiv = document.createElement("div");
            annotationDiv.className = "annotation";
            annotationDiv.style.left = `${x * viewport.scale}px`;
            annotationDiv.style.top = `${y * viewport.scale}px`;
            annotationDiv.style.width = `${width}px`;
            annotationDiv.style.height = `${height}px`;
            annotationDiv.innerText = annotation.body.value;
            // 클릭하면 상세 정보 표시
            annotationDiv.addEventListener("click", () => {
                 alert(`주석 내용: ${annotation.body.value}\n작성자: ${annotation.creator}\n생성 날짜: ${annotation.created}`);
            });
            container.appendChild(annotationDiv);
        }


      function savePDF() {
         const canvas = document.querySelector("canvas");
         const imgData = canvas.toDataURL("image/png");

         const pdf = new jsPDF();
         pdf.addImage(imgData, "PNG", 0, 0);
         pdf.save("annotated_document.pdf");
      }

    </script>
</body>
</html>

📌 3. 코드 설명

  • JSON-LD 주석 데이터를 가져와서 해당 페이지에 표시합니다.
  • PDF 문서의 특정 위치(x, y, width, height)에 주석을 출력합니다.
  • addAnnotation() 함수가 JSON-LD 데이터를 기반으로 위치를 계산하여 화면에 주석을 표시합니다.
  • JSON-LD 기반의 주석을 PDF 문서 위에 렌더링할 수 있습니다. 만약 주석 데이터가 여러 개일 경우, fetch()를 반복하여 여러 개의 주석을 추가할 수도 있습니다.
  • savePDF(): 주석이 추가된 PDF 문서를 저장하거나 내보내려면 PDF.js의 canvas 데이터를 활용하여 새로운 PDF를 생성할 수 있습니다.
728x90
반응형