Skip to content
Highlight with Bbox Coordinates Programmatically

When the PDF document is loaded, the system programmatically highlights specific regions using bounding box coordinates:

  1. Highlights multiple regions on page 2 (second page) with exact coordinates
  2. Highlights additional regions on page 3 (third page)
  3. Each highlighted region uses a different color to distinguish different areas of interest
  4. Automatically scales highlights when users zoom in/out

The bounding box coordinates define precise rectangular areas on the PDF pages, making it ideal for:

  • Highlighting table cells, form fields, or specific document sections
  • Marking regions detected by OCR or document analysis tools
  • Displaying annotations from external data sources with precise positioning
  • Visualizing search results or text/table extraction

Bounding box coordinates define rectangular regions on PDF pages:

  • pageIndex: Zero-based page number (0 for first page, 1 for second page, etc.)
  • x: Horizontal distance from the left edge of the page in points
  • y: Vertical distance from the top edge of the page in points
  • width: Width of the highlighted region in points
  • height: Height of the highlighted region in points
  • highlightColor: Color of the highlight (supports rgba, hex, or named CSS colors)
  • id: Optional unique identifier for the highlight

Coordinate System:

  • Origin (0, 0) is at the top-left corner of each page
  • Coordinates are in PDF points, where 1 point = 1/72 inch
  • Coordinates are specified at 100% zoom and automatically scaled by the viewer
  • The scale factor is calculated as scale / 100 (e.g., 150% zoom = 1.5 scale factor)

The useElementPageContext hook provides the updateElement function to programmatically add overlay elements to PDF pages. This function accepts a page number and a callback that returns React elements positioned using bounding box coordinates. The callback receives the current scale factor, allowing highlights to automatically adjust when users zoom in or out.

Here are the key concepts we’re using for this example

NameObjective
updateElementAdd custom overlay elements to specific pages based on bbox coordinates
Bounding Box (bbox)Define rectangular regions with x, y, width, and height in PDF points
Scale FactorAutomatically adjust highlight positioning for different zoom levels
import {
RPConfig,
RPProvider,
RPDefaultLayout,
RPPages,
useElementPageContext,
} from "@pdf-viewer/react";
import { useEffect } from "react";
// Define highlight data structure
const highlightDataList = [
{
id: "highlight-1",
pageIndex: 1, // Second page (zero-based)
bbox: { x: 100, y: 200, width: 300, height: 50 },
highlightColor: "rgba(255, 179, 0, 0.5)", // Orange
},
{
id: "highlight-2",
pageIndex: 1,
bbox: { x: 200, y: 300, width: 300, height: 50 },
highlightColor: "rgba(0, 0, 255, 0.5)", // Blue
},
{
id: "highlight-3",
pageIndex: 2, // Third page (zero-based)
bbox: { x: 150, y: 300, width: 250, height: 100 },
highlightColor: "rgba(255, 0, 255, 0.5)", // Magenta
},
];
// Helper function to group highlights by page
function groupByPageIndex(highlights) {
return highlights.reduce((acc, item) => {
const pageIndex = item.pageIndex;
if (!acc[pageIndex]) {
acc[pageIndex] = [];
}
acc[pageIndex].push(item);
return acc;
}, {});
}
const BboxHighlightLayer = () => {
const { updateElement } = useElementPageContext();
useEffect(() => {
// Group highlights by page for efficient rendering
const highlightsByPage = groupByPageIndex(highlightDataList);
// Iterate through each page that has highlights
for (const pageIndexStr in highlightsByPage) {
const pageIndex = Number(pageIndexStr);
const pageHighlights = highlightsByPage[pageIndex];
// Update the specified page with highlight overlays
// Note: updateElement uses 1-based page numbers
updateElement(
pageIndex + 1,
(_prevElements, _dimension, _rotate, scale) => {
// Calculate scale factor for proper positioning at any zoom level
const scaleFactor = scale / 100;
// Create a highlight overlay for each bbox on this page
return pageHighlights.map((highlight, index) => {
const { bbox, highlightColor, id } = highlight;
return (
<div
key={id || `highlight-${pageIndex}-${index}`}
style={{
position: "absolute",
// Apply scale factor to bbox coordinates
left: bbox.x * scaleFactor,
top: bbox.y * scaleFactor,
width: bbox.width * scaleFactor,
height: bbox.height * scaleFactor,
backgroundColor: highlightColor,
pointerEvents: "none",
}}
/>
);
});
}
);
}
}, [updateElement]);
return null;
};
export const AppPdfViewer = () => {
return (
<>
<RPConfig licenseKey="YOUR_LICENSE_KEY">
<RPProvider src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf">
<BboxHighlightLayer />
<RPDefaultLayout>
<RPPages />
</RPDefaultLayout>
</RPProvider>
</RPConfig>
</>
)
}

Notes:

  • The updateElement function uses 1-based page numbers, so add 1 to the zero-based pageIndex
  • The scale parameter from updateElement represents zoom percentage (100 = 100%, 150 = 150%)
  • Apply the scale factor to all bbox coordinates for proper positioning at different zoom levels
  • Use pointerEvents: "none" to prevent highlights from interfering with PDF interactions