How to save signature annotation to canvas?

Product: Webviewer
Product Version: 8.1.0

Hi, I need to create a custom annotation to show another signature appeareance. What I would like to have at the end when user drop their signature on the document , is a signature like this :
signature_digital

First step, I would like to retrieve the image signature like shown in the example “extractAnnotationSignature” at pdftron.com/documentation/web/guides/signature-tool/#export-a-signature-to-blob-storage but nothing is showing in the file 'exemple.png ’ where I export the annation.

I can’t go further to create my custom annotation :frowning:

Could you give me a hint please ? What I’m I doing wrong ?

Below is the code I use ( from Angular app )

private _onDocumentLoaded() {
		// do things that need to be done after document is loaded
		const signatureTool = this.viewer.getTool('AnnotationCreateSignature');
		this._signatureTool = signatureTool;
		this._signatureTool.addEventListener('locationSelected', (pageCoordinates: any) => {
			this.signatureCoordonnates = pageCoordinates;
			// console.log(this.signatureCoordonnates)
		});
		this._signatureTool.addEventListener('annotationAdded', (annotation: any) => {
			this.showDigitalAppearence(annotation);
		});
}

private async showDigitalAppearence(annotation: Core.Annotations.Annotation) {
	const { PDFNet, documentViewer } = this.viewerInstance.Core;
	const docPDF = await documentViewer.getDocument().getPDFDoc();
	await this.setSignatureAppearence(annotation, docPDF);
}

private async setSignatureAppearence(annotation: Core.Annotations.Annotation, docPDF: Core.PDFNet.PDFDoc) {

		const { PDFNet, documentViewer, Annotations, Math } = this.viewerInstance.Core;
		
		const data: string[] = [this._signer.lastName + ' ' + this._signer.firstName, moment().format('DD/MM/YYYY HH:mm:ss')];

		const annotationList = [];
		const annotManager = documentViewer.getAnnotationManager();
		const signCanvas = document.createElement('canvas');

		// Reference the annotation from the Document
		const pageMatrix = documentViewer.getDocument().getPageMatrix(annotation.PageNumber);

		// Set the height & width of the canvas to match the annotation
		signCanvas.height = annotation.Height;
		signCanvas.width = annotation.Width;

		const ctx = signCanvas.getContext('2d');
		// Translate the Annotation to the top Top Left Corner of the Canvas ie (0, 0)
		ctx.translate(-annotation.X, -annotation.Y);
		// Draw the Annotation onto the Canvas
		annotation.Color = new Annotations.Color(1, 215, 88)
		annotation.setX(this.signatureCoordonnates.x);
		annotation.setY(this.signatureCoordonnates.y);
		annotation.resize(new Math.Rect(this.signatureCoordonnates.x, this.signatureCoordonnates.y, this.signatureCoordonnates.x + 40, this.signatureCoordonnates.y + 40))
		annotation.draw(ctx, pageMatrix);

		signCanvas.toBlob((blob: Blob) => {
			// this.createCustomAnnotation(blob, data, annotManager, annotationList, annotation.Width, annotation.Height)
		});
        // Problem is here
        const a = document.createElement('a')
		const imgCanvas = signCanvas.toDataURL();
		a.href = imgCanvas;
		console.log(imgCanvas);
		a.download = 'example.jpg'
		a.click()
		URL.revokeObjectURL(a.href);
		
	}

	private async createCustomAnnotation(signImg, data: string[], annotManager, annotationList, width, height) {

		const { Annotations, Math, documentViewer } = this.viewerInstance.Core;

		class DigitalSignatureAnnotation extends Annotations.CustomAnnotation {
			constructor() {
				super('digitalSignature'); // provide the custom XFDF element name
				this.Subject = 'DigitalSignature';
			}
			draw(ctx, pageMatrix) {
				// the setStyles function is a function on markup annotations that sets up
				// certain properties for us on the canvas for the annotation's stroke thickness.
				this.setStyles(ctx, pageMatrix);

				const helper = new Annotations.CanvasHelper(ctx);
				const textParams = {
					fillColor: new Annotations.Color(255, 0, 0),
					opacity: 1,
					borderStyle: 'solid',
					fontSize: 5,
				}
				// first we need to translate to the annotation's x/y coordinates so that it's
				// drawn in the correct location
				ctx.translate(this.X, this.Y);
				const img = new Image();
				img.onload = (event) => {
					ctx.drawImage(event.target, 0, 0, 50, 50)
				}

				img.src = URL.createObjectURL(signImg);
				let y = 0;
				data.forEach(info => {
					helper.drawText(info, 10, y, textParams);
					const textHeigt = helper.measureText(info)['fontBoundingBoxAscent'];
					y = y + textHeigt;
				})

			}
		}

		DigitalSignatureAnnotation.prototype.elementName = 'digitalSignature';
		const customSignAnnotation = new DigitalSignatureAnnotation()
		customSignAnnotation.Width = 100;
		customSignAnnotation.Height = 200;
		customSignAnnotation.setX(this.signatureCoordonnates.x);
		customSignAnnotation.setY(this.signatureCoordonnates.y);
		customSignAnnotation.Color = new Annotations.Color(255, 0, 0);

		// annotManager.deleteAnnotations(annotManager.getAnnotationsList(), { force: false, isUndoRedo: true });
		annotationList.push(customSignAnnotation);
		annotManager.addAnnotations(annotationList);
		annotManager.drawAnnotationsFromList(annotationList);

	}

Thank you.

Hello,

Thanks for providing your code!

From looking at your code, I think you might be translating and drawing the annotation off the canvas which is why it’s coming up blank. Perhaps you could confirm that you are getting something on the canvas first?

Andy Huang

1 Like

Thank you Andy for the hint ! Indeed, I was drawing out of the canvas :slight_smile: