基于pdfjs与PDF-LIB的PDF画布点击删除数字标注功能咨询
在PDF.js查看器中实现可点击删除的数字标注
当然可以在PDF.js查看器内添加点击事件,不用纠结单纯叠加HTML的问题,结合PDF.js的渲染机制和定位逻辑就能解决。下面是具体实现思路:
1. 绑定Canvas点击事件(直接操作渲染层)
PDF.js通过Canvas渲染每一页PDF,你可以直接给Canvas绑定点击事件,然后将鼠标坐标转换为PDF内部坐标,匹配标注位置:
// 获取所有页面的Canvas元素 const canvases = document.querySelectorAll('.page canvas'); canvases.forEach((canvas, index) => { const pageNum = index + 1; // PDF页码从1开始 canvas.addEventListener('click', (e) => { // 获取当前页面的viewport(从PDF.js的viewer实例中获取) const viewport = pdfViewer.getPageView(pageNum - 1).viewport; // 将鼠标客户端坐标转换为PDF内部坐标 const rect = canvas.getBoundingClientRect(); const x = (e.clientX - rect.left) / viewport.scale; const y = (rect.bottom - e.clientY) / viewport.scale; // PDF的Y轴从底部开始计算 // 遍历标注数组,判断点击位置是否在数字标注范围内 const targetAnnotation = annotations.find(anno => { return anno.pageNum === pageNum && x >= anno.x - 10 && x <= anno.x + 10 && y >= anno.y - 10 && y <= anno.y + 10; }); if (targetAnnotation) { deleteAnnotation(targetAnnotation); } }); });
2. 准确定位叠加HTML元素(解决之前的定位失败问题)
如果想用HTML元素显示数字,关键是基于PDF.js的页面容器和viewport计算准确位置:
// 假设标注对象格式:{ id: 'anno1', pageNum: 2, x: 100, y: 200, number: '1' } function renderAnnotation(annotation) { const pageView = pdfViewer.getPageView(annotation.pageNum - 1); const viewport = pageView.viewport; const pageContainer = pageView.div; // 将PDF坐标转换为HTML容器内的坐标 const htmlCoords = viewport.convertToViewportPoint(annotation.x, annotation.y); // 转换PDF Y轴为HTML Y轴(从上到下) const htmlY = viewport.height - htmlCoords[1]; // 创建数字元素 const numElement = document.createElement('span'); numElement.textContent = annotation.number; numElement.style.cssText = ` position: absolute; left: ${htmlCoords[0]}px; top: ${htmlY}px; padding: 2px 6px; background: #ffeb3b; cursor: pointer; z-index: 10; `; numElement.dataset.annoId = annotation.id; // 添加点击删除事件 numElement.addEventListener('click', () => { // 从标注数组移除 annotations = annotations.filter(anno => anno.id !== annotation.id); // 移除HTML元素 numElement.remove(); // 用PDF-LIB更新PDF文档 updatePDFAfterDelete(annotation); }); pageContainer.appendChild(numElement); }
3. 结合PDF-LIB完成持久化删除
删除标注后,需要用PDF-LIB加载原PDF,移除对应的文本标注并重新生成:
async function updatePDFAfterDelete(annotation) { // 加载原PDF文档 const pdfDoc = await PDFLib.PDFDocument.load(originalPdfBytes); const targetPage = pdfDoc.getPages()[annotation.pageNum - 1]; // 根据你添加标注时的逻辑,移除对应内容(示例需结合实际存储调整) // 建议维护标注与PDF-LIB操作的映射表,方便精准删除 // 保存修改后的PDF const modifiedPdfBytes = await pdfDoc.save(); // 更新PDF.js查看器显示新文档 loadModifiedPDF(modifiedPdfBytes); }
关键注意点
- 监听PDF.js的
pagerendered事件,在页面渲染完成后再渲染标注,避免滚动后标注丢失 - 处理缩放逻辑:监听
scalechanged事件,缩放时重新计算标注元素位置 - 保持数据一致性:确保内存标注数组、HTML元素、PDF-LIB中的标注三者同步
内容的提问来源于stack exchange,提问作者adrian thuo
相关产品推荐
相关产品推荐

