Feature Request: Measurement Tool for PDF Viewer #2902
Replies: 1 comment 1 reply
-
I believe you can implement this feature yourself. So I've asked ChatGPT how to do it. The ideas it proposes sound promising. Usually, ChatGPT doesn't get everything right, but I think it's a decent head-start. What Chat didn't mention is you can add a custom button to activate rulers and measuring. I'd suggest you start implementing the feature, and when it works, I'll add it to ngx-extended-pdf-viewer (if you allow me to do so, of course - it's up to you to donate your code or not). That said, here's what ChatGPT says and suggests, with a few edits from me: Your proposed idea is technically feasible but non-trivial to implement in ngx-extended-pdf-viewer. Here’s a breakdown of the feasibility and how you could go about implementing it, including some architectural considerations: ⸻ ✅ What’s possible with ngx-extended-pdf-viewer? ngx-extended-pdf-viewer is a wrapper around Mozilla’s pdf.js, with many extensions and customizations for Angular. It provides a solid base for rendering PDFs, overlays, and interacting with pages, but does not include a measurement tool out of the box. However, it exposes the underlying PDF canvas and rendering layers, which allows for custom extensions like a measurement tool. ⸻ 🔧 Implementation Strategy
You can add a custom overlay layer (e.g., SVG or HTML canvas) on top of the PDF canvas to capture mouse events: Angular makes managing this interaction straightforward using event bindings and services for shared state.
PDFs use 1 point = 1/72 inch, but:
You’ll calculate real-world units as: const distanceInPoints = Math.sqrt((dx)^2 + (dy)^2);
const distanceInInches = distanceInPoints / 72;
const distanceInCm = distanceInInches * 2.54; Make sure to take page scale and zoom level into account using viewport.transform.
You can overlay SVG or HTML elements for:
You can create a service (e.g., MeasurementService) that: ⸻
⸻ 🛠️ Realistic Scope You can build this as: ⸻ ✅ Verdict Yes, you can implement a measurement tool in ngx-extended-pdf-viewer, but it will require a custom overlay and detailed handling of rendering transforms. It’s not built-in, but the viewer is extensible enough to support this. As mentioned before, if you run into a missing API, ask Stephan to provide it. Here’s a proposed Angular component and service architecture for adding a measurement tool to ngx-extended-pdf-viewer. ⸻ 📐 Feature Goals Recap ⸻ 📁 Component + Service Structure
A transparent overlay positioned over the PDF canvas. @Component({
selector: 'app-pdf-measurement-overlay',
template: `<canvas #overlayCanvas></canvas>`,
styles: [`
canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
`]
})
export class PdfMeasurementOverlayComponent implements AfterViewInit {
@ViewChild('overlayCanvas', { static: true }) overlayCanvas!: ElementRef<HTMLCanvasElement>;
private ctx!: CanvasRenderingContext2D;
private start: { x: number, y: number } | null = null;
constructor(private measurementService: MeasurementService) {}
ngAfterViewInit() {
this.ctx = this.overlayCanvas.nativeElement.getContext('2d')!;
this.resizeCanvas();
this.attachEvents();
}
resizeCanvas() {
const canvas = this.overlayCanvas.nativeElement;
const viewerContainer = document.querySelector('.pdfViewer') as HTMLElement;
if (viewerContainer) {
canvas.width = viewerContainer.scrollWidth;
canvas.height = viewerContainer.scrollHeight;
canvas.style.width = viewerContainer.scrollWidth + 'px';
canvas.style.height = viewerContainer.scrollHeight + 'px';
}
}
attachEvents() {
const canvas = this.overlayCanvas.nativeElement;
canvas.parentElement!.addEventListener('mousedown', (e) => {
this.start = { x: e.offsetX, y: e.offsetY };
});
canvas.parentElement!.addEventListener('mousemove', (e) => {
if (this.start) {
this.drawMeasurement(this.start, { x: e.offsetX, y: e.offsetY });
}
});
canvas.parentElement!.addEventListener('mouseup', (e) => {
if (this.start) {
const end = { x: e.offsetX, y: e.offsetY };
this.measurementService.recordMeasurement(this.start, end);
this.start = null;
}
});
}
drawMeasurement(start: { x: number, y: number }, end: { x: number, y: number }) {
const canvas = this.overlayCanvas.nativeElement;
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
this.ctx.beginPath();
this.ctx.moveTo(start.x, start.y);
this.ctx.lineTo(end.x, end.y);
this.ctx.strokeStyle = 'red';
this.ctx.lineWidth = 2;
this.ctx.stroke();
const distance = this.measurementService.calculateDistance(start, end);
this.ctx.fillText(`${distance.toFixed(2)} cm`, (start.x + end.x) / 2, (start.y + end.y) / 2);
}
} ⸻
This service handles unit conversion, stores measurements, and can expose them to the outside. @Injectable({ providedIn: 'root' })
export class MeasurementService {
private measurements: { start: { x: number, y: number }, end: { x: number, y: number }, cm: number }[] = [];
// Assume fixed DPI or expose setter
private readonly dpi = 96;
private readonly pointsPerInch = 72;
// Could factor in viewport scaling if needed
private scale = 1;
setScale(scale: number) {
this.scale = scale;
}
recordMeasurement(start: { x: number, y: number }, end: { x: number, y: number }) {
const cm = this.calculateDistance(start, end);
this.measurements.push({ start, end, cm });
}
calculateDistance(start: { x: number, y: number }, end: { x: number, y: number }): number {
const dx = (end.x - start.x) / this.scale;
const dy = (end.y - start.y) / this.scale;
const distanceInPixels = Math.sqrt(dx * dx + dy * dy);
const inches = distanceInPixels / this.dpi;
return inches * 2.54;
}
getAllMeasurements() {
return this.measurements;
}
} ⸻ 🔌 Integration In your pdf-viewer.component.html: <ngx-extended-pdf-viewer
[src]="'assets/your-pdf.pdf'"
useBrowserLocale="true"
height="100vh"
></ngx-extended-pdf-viewer>
<app-pdf-measurement-overlay></app-pdf-measurement-overlay> Make sure the overlay is absolutely positioned over the .pdfViewer. ⸻ 🚀 Possible Enhancements ⸻ ✅ Summary You now have a clean separation: (Stephan's back): as mentioned before, I didn't try the code Chat generated, but I'm positive it's pointing into the right direction. Boa sorte e divirta-se! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello maintainers,
I would like to propose a new feature: a measurement tool that allows users to measure distances directly within the PDF viewer.
Why is this feature important?
Many applications require precise measurement of elements within a PDF, such as lines, sections, or annotations. This is particularly useful for architectural blueprints, technical drawings, and official documents.
Suggested Implementation Approach:
Benefits:
Would this be a feasible addition to the library? I’d be happy to assist in development and testing if this feature is considered. Looking forward to your thoughts!
Best regards,
Ana Genova
Beta Was this translation helpful? Give feedback.
All reactions