Render the highlight areas

The highlight plugin provides the ability of adding annotations to the selected text. It highlights multiple areas that are determined based on the bounding rectangles of selected text items.
There are associations where we still want to show the highlight areas without selecting texts in the document.
The highlight plugin allows us to choose how the highlight actions can be triggered via the `trigger` option. It has two possible values:
ValueDescriptionFrom
`Trigger.TextSelection`Show the target after users select text. It is the default value2.10.0
`Trigger.None`Doesn't trigger the highlight. It is often used to render the highlight areas2.10.0
In our specific case, we probably want to use the `Trigger.None` option:
import { highlightPlugin, Trigger } from '@react-pdf-viewer/highlight';
const highlightPluginInstance = highlightPlugin({
trigger: Trigger.None,
});

Render the areas

As mentioned in the highlight plugin page, each highlight area defines the bounding rectangle:
interface HighlightArea {
height: number;
left: number;
pageIndex: number;
top: number;
width: number;
}
The `left` and `top` properties are the distances from the top-left corner to the left and top side of the corresponding page. While the `height` and `width` properties indicate the height and width of the area, respectively. All those properties are the number of percentages, not the absolute values in pixels. So the highlight areas are kept when we zoom the document.
The `pageIndex` property is the index of the page that the area belongs to.
In order to render the highlight areas in each page of the document, we can use the `renderHighlights` function:
import type { HighlightArea, RenderHighlightsProps } from '@react-pdf-viewer/highlight';
const renderHighlights = (props: RenderHighlightsProps) => (
// ...
);
const highlightPluginInstance = highlightPlugin({
renderHighlights,
trigger: Trigger.None,
});
The `renderHighlights` function is called when the `Viewer` component renders each page, hence we have to filter the highlight areas in the current page first. The sample code below assumes that the `areas` variable represents the full list of highlight areas.
const renderHighlights = (props: RenderHighlightsProps) => (
<div>{areas.filter((area) => area.pageIndex === props.pageIndex)}</div>
);
Each highlight area item is displayed at an absolute position within the corresponding page. The area has to zoom or rotate automatically when users zoom or rotate the document.
Fortunately, you don't have to do these calculations yourself. The `RenderHighlightsProps` type calculates the position and returns the needed styles via the `getCssProperties(area, rotation)` function.
We just simply apply the CSS style returned from this function to each highlight area:
const renderHighlights = (props: RenderHighlightsProps) => (
<div>
{areas
.filter((area) => area.pageIndex === props.pageIndex)
.map((area, idx) => (
<div
key={idx}
className="highlight-area"
style={Object.assign(
{},
{
background: 'yellow',
opacity: 0.4,
},
// Calculate the position
// to make the highlight area displayed at the desired position
// when users zoom or rotate the document
props.getCssProperties(area, props.rotation)
)}
/>
))}
</div>
);
The following demonstration uses the hard coded highlight areas:
areas={[
{
pageIndex: 3,
height: 1.55401,
width: 28.1674,
left: 27.5399,
top: 15.0772,
},
{
pageIndex: 3,
height: 1.32637,
width: 37.477,
left: 55.7062,
top: 15.2715,
},
{
pageIndex: 3,
height: 1.55401,
width: 28.7437,
left: 16.3638,
top: 16.6616,
},
]}
In reality, you might need to load them from the back-end.
Scroll to the fourth page to see the highlight areas (The sample code)

See also