class Annotation { static createAnnotations(document) { const signatures = [] document.elements.forEach((element) => { const [annotation, formField] = Annotation.createSignature(element) signatures.push(annotation) signatures.push(formField) }) return { signatures: signatures } } static createSignature(element) { const id = PSPDFKit.generateInstantId() const width = Annotation.inchToPoint(element.width) const height = Annotation.inchToPoint(element.height) const top = Annotation.inchToPoint(element.top) - height / 2 const left = Annotation.inchToPoint(element.left) - width / 2 const page = element.page - 1 console.log(id) const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ id: id, pageIndex: page, formFieldName: id, backgroundColor: PSPDFKit.Color.YELLOW, blendMode: 'multiply', boundingBox: new PSPDFKit.Geometry.Rect({ width, height, top, left, }), }) const formField = new PSPDFKit.FormFields.SignatureFormField({ name: id, annotationIds: PSPDFKit.Immutable.List([annotation.id]), }) return [annotation, formField] } static createTextBox(element) { const id = PSPDFKit.generateInstantId() const width = Annotation.inchToPoint(element.width) const height = Annotation.inchToPoint(element.height) const top = Annotation.inchToPoint(element.top) - height / 2 const left = Annotation.inchToPoint(element.left) - width / 2 const page = element.page - 1 //shift top += height + 10 const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ id: id, pageIndex: page, formFieldName: id, backgroundColor: PSPDFKit.Color.YELLOW, blendMode: 'multiply', boundingBox: new PSPDFKit.Geometry.Rect({ width, height, top, left, }), }) const formField = new PSPDFKit.FormFields.SignatureFormField({ name: id, annotationIds: PSPDFKit.Immutable.List([annotation.id]), }) return [annotation, formField] } static createText static async getAnnotations(instance) { const array = await Promise.all( Array.from({ length: instance.totalPageCount }).map((_, pageIndex) => instance.getAnnotations(pageIndex) ) ) return array.flatMap((annotations) => annotations.reduce((acc, annotation) => acc.concat(annotation), []) ) } static async deleteAnnotations(instance) { const allAnnotations = await Annotation.getAnnotations(instance) const pageAnnotations = allAnnotations.filter(Annotation.isSignature) //deleting all Annotations return await instance.delete(pageAnnotations) } static async validateAnnotations(instance) { const allAnnotations = await Annotation.getAnnotations(instance) const pageAnnotations = allAnnotations .map((annotation) => { return annotation }) return true } static isSignature(annotation) { return !!annotation.isSignature || annotation.description == 'FRAME' } static createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) { const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({ pageIndex: pageIndex, isSignature: false, readOnly: true, locked: true, lockedContents: true, contentType: 'image/png', imageAttachmentId, description: 'FRAME', boundingBox: boundingBox, }) return frameAnnotation } static async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) { const canvas = document.createElement('canvas') const scale = 4 const fontSize = 10 canvas.width = width * scale canvas.height = height * scale const ctx = canvas.getContext('2d') // This supposedly makes the lines and text less blurry // See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry ctx.translate(0.5, 0.5) // This also should make the lines and text less blurry ctx.textRendering = "geometricPrecision" const date = timestamp const dateString = date.toLocaleString('de-DE') const signatureLength = 100 * scale const signatureString = receiverSignature.substring(0, 15) + "…" ctx.beginPath() ctx.moveTo(30 * scale, 10 * scale) ctx.lineTo(signatureLength, 10 * scale) ctx.moveTo(30 * scale, 10 * scale) ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale) ctx.moveTo(10 * scale, 30 * scale) ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale) ctx.moveTo(30 * scale, 50 * scale) ctx.lineTo(signatureLength, 50 * scale) ctx.strokeStyle = 'darkblue' ctx.stroke() ctx.fillStyle = 'black' ctx.font = `${fontSize * scale}px sans-serif` ctx.fillText('Signed by', 15 * scale, 10 * scale) ctx.fillText(receiverName, 15 * scale, 60 * scale) ctx.fillText(signatureString, 15 * scale, 70 * scale) return new Promise((resolve) => { canvas.toBlob((blob) => { const url = URL.createObjectURL(blob) resolve(url) }) }) } static inchToPoint(inch) { return inch * 72 } }