Angular17实现PDF选定区域矩形绘制及OCR坐标获取的问题
问题解决方案
问题1:Canvas遮挡PDF查看器控件
你的canvas设置了z-index:1,直接覆盖在PDF查看器上方,导致所有点击事件都被canvas拦截,控件自然无法使用。解决办法:
- 给canvas添加
pointer-events: none,让它默认不拦截鼠标事件 - 仅在绘制阶段临时开启canvas的
pointer-events: auto,绘制完成后再关闭
问题2:绘制矩形与选定区域偏差大
偏差核心原因是canvas的显示尺寸和内部绘图缓冲区尺寸不匹配,加上PDF的缩放、分页影响,坐标没有正确转换。解决步骤:
- 同步canvas的
width/height属性(内部绘图尺寸)与CSS宽高(显示尺寸) - 获取PDF页面的缩放比例,将鼠标的容器相对坐标转换为PDF页面的实际坐标
- 结合当前页码修正Y轴坐标,抵消分页带来的偏移
修改后的代码
HTML部分
<div style="position: relative;width: 50%;height: 90vh;" class="col-6" #pdfContainer> <ngx-extended-pdf-viewer [base64Src]="base64string.split(',')[1]" height="90vh" [zoom]="'page-actual'" [useBrowserLocale]="true" [textLayer]="true" [showHandToolButton]="true" (pageChange)="onPageChange($event)"> </ngx-extended-pdf-viewer> <canvas #drawCanvas style="position: absolute; top: 0; left: 0; z-index: 1; width: 100%; height: 100%;border: red 2px solid; pointer-events: none;" (mousedown)="onMouseDown($event)" (mouseup)="onMouseUp($event)"></canvas> </div>
TypeScript部分
import { Component, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-pdf-annotator', templateUrl: './pdf-annotator.component.html', styleUrls: ['./pdf-annotator.component.css'] }) export class PdfAnnotatorComponent { base64string: string = ''; fileDroped: boolean = false; startX: number = 0; startY: number = 0; endX: number = 0; endY: number = 0; isDrawing: boolean = false; currentPage: number = 1; @ViewChild('drawCanvas') drawCanvas!: ElementRef<HTMLCanvasElement>; @ViewChild('pdfContainer') pdfContainer!: ElementRef<HTMLElement>; onPageChange(page: number) { this.currentPage = page; // 切换页面时清空画布 const ctx = this.drawCanvas.nativeElement.getContext('2d'); if (ctx) { ctx.clearRect(0, 0, this.drawCanvas.nativeElement.width, this.drawCanvas.nativeElement.height); } } ngAfterViewInit() { // 同步canvas内部尺寸和显示尺寸 const canvas = this.drawCanvas.nativeElement; const container = this.pdfContainer.nativeElement; canvas.width = container.clientWidth; canvas.height = container.clientHeight; // 监听窗口 resize,同步canvas尺寸 window.addEventListener('resize', () => { canvas.width = container.clientWidth; canvas.height = container.clientHeight; }); } onMouseDown(event: MouseEvent) { if (!this.fileDroped) return; const canvas = this.drawCanvas.nativeElement; const container = this.pdfContainer.nativeElement; // 临时开启canvas鼠标事件监听 canvas.style.pointerEvents = 'auto'; const rect = container.getBoundingClientRect(); // 获取相对于容器的坐标 this.startX = event.clientX - rect.left; this.startY = event.clientY - rect.top; this.isDrawing = true; } onMouseUp(event: MouseEvent) { if (!this.fileDroped || !this.isDrawing) return; const canvas = this.drawCanvas.nativeElement; const container = this.pdfContainer.nativeElement; const rect = container.getBoundingClientRect(); this.endX = event.clientX - rect.left; this.endY = event.clientY - rect.top; const ctx = canvas.getContext('2d'); if (ctx) { ctx.strokeStyle = 'blue'; ctx.lineWidth = 2; // 修正坐标,确保宽高为正 const x = Math.min(this.startX, this.endX); const y = Math.min(this.startY, this.endY); const width = Math.abs(this.endX - this.startX); const height = Math.abs(this.endY - this.startY); ctx.strokeRect(x, y, width, height); // 转换为PDF页面的相对坐标(默认A4尺寸:宽595px,高842px,可根据实际PDF调整) const pdfPageWidth = 595; const pdfPageHeight = 842; const scale = container.clientWidth / pdfPageWidth; const pdfX = x / scale; const pdfY = (y - (this.currentPage - 1) * pdfPageHeight * scale) / scale; const pdfWidth = width / scale; const pdfHeight = height / scale; console.log(`PDF页面坐标:X=${pdfX.toFixed(2)}, Y=${pdfY.toFixed(2)}, 宽=${pdfWidth.toFixed(2)}, 高=${pdfHeight.toFixed(2)}`); } // 关闭canvas鼠标事件监听,避免遮挡控件 canvas.style.pointerEvents = 'none'; this.isDrawing = false; } }
ng2-pdf-viewer无法显示的排查点
如果file和base64两种方式都失效,检查以下内容:
- 确认依赖安装完整:
npm install ng2-pdf-viewer pdfjs-dist - 检查base64格式:如果包含
data:application/pdf;base64,前缀,直接绑定[src]="base64string"即可,无需split - 查看浏览器控制台报错:排查是否存在CORS限制、PDF文件损坏或版本兼容问题
内容的提问来源于stack exchange,提问作者john younan
相关产品推荐
相关产品推荐

