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

如何基于react-pdf实现PDF内容高亮标注功能?

实现React-PDF的文本高亮标注功能

核心思路

react-pdf本身没有内置标注API,但可以通过它的onTextRender回调捕获每个文本块的位置与内容,再在PDF渲染容器的上层叠加绝对定位的高亮元素,配合按钮事件控制高亮的显示范围。

具体实现步骤

1. 基础结构搭建

先完成PDF加载和按钮布局的基础代码:

import { Document, Page } from 'react-pdf';
import { useState, useRef } from 'react';

export default function PDFHighlighter() {
  const [numPages, setNumPages] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);
  const [highlightType, setHighlightType] = useState(null); // 存储当前高亮类型:'title'/'author'/null
  const [textBlocks, setTextBlocks] = useState([]); // 存储所有文本块数据
  const pdfContainerRef = useRef(null);

  // PDF加载完成回调
  function onDocumentLoadSuccess({ numPages }) {
    setNumPages(numPages);
  }

  // 捕获文本渲染时的元数据
  function onTextRender(textItem) {
    // 收集每个文本块的关键信息:内容、位置、页码
    const blockData = {
      text: textItem.str,
      position: textItem.transform, // [缩放X, 倾斜, 倾斜, 缩放Y, 偏移X, 偏移Y]
      pageNumber: currentPage,
      width: textItem.width,
      height: textItem.height,
      fontSize: textItem.fontSize // 可用于优化匹配规则
    };
    setTextBlocks(prev => [...prev, blockData]);
  }

  return (
    <div>
      <div className="controls">
        <button onClick={() => setHighlightType('title')}>高亮标题</button>
        <button onClick={() => setHighlightType('author')}>高亮作者</button>
        <button onClick={() => setHighlightType(null)}>取消高亮</button>
      </div>
      <div ref={pdfContainerRef} className="pdf-container">
        <Document
          file="your-pdf-file.pdf"
          onLoadSuccess={onDocumentLoadSuccess}
        >
          <Page
            pageNumber={currentPage}
            onTextRender={onTextRender}
            scale={1.5} // 可根据需求调整缩放比例
          />
        </Document>
        {/* 高亮元素将渲染在这里 */}
        {renderHighlights()}
      </div>
      <div className="pagination">
        <button onClick={() => {
          setTextBlocks([]);
          setCurrentPage(prev => Math.max(prev - 1, 1));
        }} disabled={currentPage === 1}>上一页</button>
        <span>第 {currentPage} 页 / 共 {numPages} 页</span>
        <button onClick={() => {
          setTextBlocks([]);
          setCurrentPage(prev => Math.min(prev + 1, numPages));
        }} disabled={currentPage === numPages}>下一页</button>
      </div>
    </div>
  );
}

2. 实现高亮元素渲染

添加renderHighlights函数,根据当前高亮类型筛选匹配的文本块,计算绝对位置后渲染高亮层:

function renderHighlights() {
  if (!highlightType || !pdfContainerRef.current) return null;

  // 定义匹配规则:根据实际PDF内容调整
  const matchRule = {
    title: (block) => {
      // 示例:匹配第一页、字号大于16、内容长度符合标题特征的文本
      return block.pageNumber === 1 && block.fontSize > 16 && block.text.length > 10;
    },
    author: (block) => {
      // 示例:匹配包含"作者"或"By:"关键词的文本
      return block.text.includes('作者') || block.text.startsWith('By: ');
    }
  };

  // 筛选当前页需要高亮的文本块
  const filteredBlocks = textBlocks.filter(block => {
    return block.pageNumber === currentPage && matchRule[highlightType](block);
  });

  return filteredBlocks.map((block, index) => {
    // 从transform数组中提取偏移量和缩放比例,计算绝对位置
    const [scaleX, , , scaleY, offsetX, offsetY] = block.position;
    
    return (
      <div
        key={index}
        className="highlight-box"
        style={{
          position: 'absolute',
          left: `${offsetX * scaleX}px`,
          top: `${offsetY * scaleY}px`,
          width: `${block.width * scaleX}px`,
          height: `${block.height * scaleY}px`,
          backgroundColor: 'rgba(255, 255, 0, 0.3)', // 半透明黄色高亮
          pointerEvents: 'none', // 不干扰PDF交互
          zIndex: 10
        }}
      />
    );
  });
}

3. 样式补充

给容器和高亮层添加基础样式:

.pdf-container {
  position: relative;
  overflow: auto;
  max-width: 100%;
}

.highlight-box {
  border-radius: 2px;
}

.controls {
  margin-bottom: 16px;
  gap: 8px;
  display: flex;
}

.pagination {
  margin-top: 16px;
  display: flex;
  gap: 16px;
  align-items: center;
}

关键注意事项

  • 文本块匹配规则:需要根据你的PDF实际内容调整matchRule里的判断逻辑,比如结合文本的字号、位置、关键词等维度优化匹配精度。
  • 页码切换处理:切换页码时必须清空旧的文本块数据,避免跨页高亮混乱,代码中已在分页按钮点击时重置textBlocks。
  • 缩放适配:如果允许用户调整PDF缩放比例,需要把scale存在state中,计算高亮位置时使用当前的scale值。
  • 长文本拆分:如果标题/作者被拆分成多个文本块,需要合并相邻的匹配块,避免出现多个分散的高亮框(可通过比较文本块的位置坐标实现合并)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:20:40