DanielArnould / react-pdf-highlighter-extended

📄 Set of modern React components for PDF highlighting
https://danielarnould.github.io/react-pdf-highlighter-extended/example-app/
MIT License
43 stars 16 forks source link

Download PDF with area highlighted fields #11

Open ctle-vn opened 3 months ago

ctle-vn commented 3 months ago

Hi folks,

Absolutely love this project, thanks again for so many features. I was able to get a local instance working with area and text highlights. I was wondering if it was supported in the package to download the PDF with the highlighted areas?

I did the following:

import { PDFDocument, rgb } from "pdf-lib"

interface CommentedHighlight extends Highlight {
  comment?: string
  pageNumber: number
}

export async function savePdfWithHighlights(
  pdfUrl: string,
  highlights: Array<CommentedHighlight>
) {
  // Fetch the original PDF document
  const existingPdfBytes = await fetch(pdfUrl).then((res) => res.arrayBuffer())

  // Load a PDFDocument from the existing PDF bytes
  const pdfDoc = await PDFDocument.load(existingPdfBytes)

  // Get the pages of the document
  const pages = pdfDoc.getPages()

  // Draw highlights on the pages
  highlights.forEach((highlight) => {
    console.log(`Drawing highlight: ${JSON.stringify(highlight.position)}`)
    const { position, pageNumber } = highlight
    const page = pages[pageNumber - 1] // Pages are zero-indexed

    if (position && position.boundingRect) {
      const { x1, y1, x2, y2 } = position.boundingRect
      const width = x2 - x1
      const height = y2 - y1

      // Convert to PDFLib coordinates
      const pdfX = x1
      const pdfY = y2 // Ensure correct Y-axis calculation
      console.log(
        `Drawing rectangle at (${pdfX}, ${pdfY}) with width ${width} and height ${height}`
      )
      page.drawRectangle({
        x: pdfX,
        y: pdfY,
        width: width,
        height: height,
        color: rgb(1, 1, 0), // Yellow color for highlight
        opacity: 0.5, // 50% opacity for highlight
      })
    }
  })

  // Serialize the PDFDocument to bytes (a Uint8Array)
  const pdfBytes = await pdfDoc.save()

  // Trigger the browser to download the PDF document
  const blob = new Blob([pdfBytes], { type: "application/pdf" })
  const link = document.createElement("a")
  link.href = URL.createObjectURL(blob)
  link.download = "highlighted.pdf"
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

But my issue is that in the download pdf, the highlighted areas are scaled much larger and misaligned.

Would love any advice on this, thanks yall.