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

PDF.js添加批注功能:求简单高亮/画笔工具可用示例

简易PDF.js高亮/画笔批注工具实现示例

针对你提到的PDF.js官方批注功能尚未发布、web viewer代码难以整合的问题,这里提供两个基于基础PDF.js API的简易工具实现,无需依赖复杂的viewer组件:

一、简易高亮工具

核心思路是监听鼠标事件,在canvas上绘制半透明矩形模拟高亮效果,同时支持临时预览和确认:

async function initPDFWithHighlight() {
  // 加载PDF文档
  const pdf = await pdfjsLib.getDocument('target.pdf').promise;
  const page = await pdf.getPage(1);
  const viewport = page.getViewport({ scale: 1.5 });

  // 初始化canvas
  const canvas = document.getElementById('pdf-canvas');
  const ctx = canvas.getContext('2d');
  canvas.height = viewport.height;
  canvas.width = viewport.width;

  // 渲染初始页面
  await page.render({ canvasContext: ctx, viewport }).promise;

  // 高亮状态变量
  let isHighlighting = false;
  let startPos = { x: 0, y: 0 };
  let endPos = { x: 0, y: 0 };

  // 鼠标按下:记录起始点
  canvas.addEventListener('mousedown', (e) => {
    isHighlighting = true;
    const rect = canvas.getBoundingClientRect();
    startPos = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
  });

  // 鼠标移动:实时绘制临时高亮
  canvas.addEventListener('mousemove', async (e) => {
    if (!isHighlighting) return;
    const rect = canvas.getBoundingClientRect();
    endPos = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };

    // 重新渲染页面清除临时绘制
    await page.render({ canvasContext: ctx, viewport }).promise;

    // 绘制高亮矩形
    ctx.fillStyle = 'rgba(255, 255, 0, 0.3)';
    const x = Math.min(startPos.x, endPos.x);
    const y = Math.min(startPos.y, endPos.y);
    const width = Math.abs(endPos.x - startPos.x);
    const height = Math.abs(endPos.y - startPos.y);
    ctx.fillRect(x, y, width, height);
  });

  // 鼠标释放:结束高亮绘制,可在此保存批注数据
  canvas.addEventListener('mouseup', () => {
    isHighlighting = false;
    // 示例:存储高亮区域信息
    // savedHighlights.push({ x, y, width, height, pageNum: 1 });
  });
}

// 初始化调用
initPDFWithHighlight();

二、简易画笔工具

通过监听鼠标路径,在canvas上直接绘制自由线条,实现基础画笔功能:

async function initPDFWithBrush() {
  // 加载PDF文档(同高亮工具的初始化逻辑)
  const pdf = await pdfjsLib.getDocument('target.pdf').promise;
  const page = await pdf.getPage(1);
  const viewport = page.getViewport({ scale: 1.5 });
  const canvas = document.getElementById('pdf-canvas');
  const ctx = canvas.getContext('2d');
  canvas.height = viewport.height;
  canvas.width = viewport.width;
  await page.render({ canvasContext: ctx, viewport }).promise;

  // 画笔状态变量
  let isDrawing = false;
  let lastPoint = { x: 0, y: 0 };
  let currentTool = 'brush'; // 可通过按钮切换工具

  // 工具切换示例(可添加HTML按钮绑定)
  document.getElementById('switch-brush').addEventListener('click', () => {
    currentTool = 'brush';
  });
  document.getElementById('switch-highlight').addEventListener('click', () => {
    currentTool = 'highlight';
  });

  // 鼠标按下:开始绘制
  canvas.addEventListener('mousedown', (e) => {
    if (currentTool !== 'brush') return;
    isDrawing = true;
    const rect = canvas.getBoundingClientRect();
    lastPoint = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
  });

  // 鼠标移动:绘制路径
  canvas.addEventListener('mousemove', (e) => {
    if (!isDrawing || currentTool !== 'brush') return;
    const rect = canvas.getBoundingClientRect();
    const currentPoint = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };

    ctx.beginPath();
    ctx.moveTo(lastPoint.x, lastPoint.y);
    ctx.lineTo(currentPoint.x, currentPoint.y);
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#ff0000';
    ctx.lineCap = 'round'; // 线条端点圆润
    ctx.stroke();

    lastPoint = currentPoint;
  });

  // 鼠标释放:结束绘制
  canvas.addEventListener('mouseup', () => {
    isDrawing = false;
  });
}

// 初始化调用
initPDFWithBrush();

注意事项

  • 上述示例仅实现了前端可视化效果,若需要持久化批注,需将批注的坐标、样式、页码等信息存储(如localStorage或后端),下次加载页面时重新绘制
  • 可根据需求调整高亮的颜色、透明度,画笔的粗细、颜色等参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 06:22:37