You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用react-pdf-viewer实现PDF段落/句子的程序化高亮?

解决react-pdf-viewer段落/句子高亮问题

你当前使用searchPlugin的highlight方法仅支持单个搜索词高亮,要实现段落、句子级别的高亮,需结合highlightPlugin与PDF文本定位能力完成,具体方案如下:

1. 替换插件并初始化

移除searchPlugin,改用highlightPlugin,确保依赖引入正确:

import PropTypes from "prop-types";
import { Worker, Viewer, SpecialZoomLevel } from "@react-pdf-viewer/core";
import { highlightPlugin } from "@react-pdf-viewer/highlight";
import "@react-pdf-viewer/highlight/lib/styles/index.css";
import * as pdfjsLib from "pdfjs-dist";
import "@react-pdf-viewer/default-layout/lib/styles/index.css";
import { useEffect, useState, useRef } from "react";

2. 完整实现代码

通过pdfjs API获取PDF每页文本,匹配目标段落的位置后生成高亮数据:

export default function PDFView({ pdfUrl, highlightedText }) {
    const highlightPluginInstance = highlightPlugin();
    const { addHighlights } = highlightPluginInstance;
    const viewerRef = useRef(null);
    const [documentLoaded, setDocumentLoaded] = useState(false);

    useEffect(() => {
        if (!documentLoaded || !highlightedText) return;

        const fetchAndHighlight = async () => {
            // 加载PDF文档
            const loadingTask = pdfjsLib.getDocument({ url: pdfUrl });
            const pdfDoc = await loadingTask.promise;
            const highlights = [];

            // 遍历每页查找目标文本
            for (let pageNum = 1; pageNum <= pdfDoc.numPages; pageNum++) {
                const page = await pdfDoc.getPage(pageNum);
                const textContent = await page.getTextContent();
                // 拼接当前页文本,方便匹配
                const pageText = textContent.items.map(item => item.str).join(" ");

                // 匹配目标段落(可根据需求替换为精确匹配逻辑)
                if (pageText.includes(highlightedText)) {
                    // 收集匹配到的文本片段坐标
                    const matchedSegments = textContent.items.filter(item => highlightedText.includes(item.str));
                    matchedSegments.forEach(item => {
                        highlights.push({
                            pageIndex: pageNum - 1, // react-pdf-viewer使用0起始页码
                            rects: [
                                {
                                    x: item.transform[4],
                                    y: item.transform[5],
                                    width: item.width,
                                    height: item.height,
                                },
                            ],
                            text: item.str,
                            id: `${pageNum}-${Math.random()}`, // 生成唯一标识
                        });
                    });
                }
            }

            // 批量添加高亮
            addHighlights(highlights);
        };

        fetchAndHighlight();
    }, [documentLoaded, highlightedText, pdfUrl, addHighlights]);

    return (
        <div className="border-solid border-2 rounded-md border-slate-300 h-screen w-auto overflow-auto overscroll-contain">
            <Worker workerUrl={`https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.js`}>
                <Viewer
                    ref={viewerRef}
                    fileUrl={pdfUrl}
                    defaultScale={SpecialZoomLevel.PageFit}
                    onDocumentLoad={() => setDocumentLoaded(true)}
                    plugins={[highlightPluginInstance]}
                />
            </Worker>
        </div>
    );
}

PDFView.propTypes = {
    pdfUrl: PropTypes.string.isRequired,
    highlightedText: PropTypes.string.isRequired,
};

关键细节说明

  • 文本匹配逻辑:示例用includes做模糊匹配,若需精确匹配完整段落,可调整为按换行分割文本或用正则表达式匹配。
  • 坐标处理:从textContent.items中提取文本片段的坐标,若要高亮完整连续段落,可将相邻文本片段的rect合并为一个大区域。
  • 跨页处理:如果目标段落跨多页,循环遍历每页时会自动在对应页面生成高亮。

内容的提问来源于stack exchange,提问作者neil_ruaro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:35:00