Skip to content

Commit 9a9cd90

Browse files
committed
feat: add reusing signatures example
1 parent 02455b3 commit 9a9cd90

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import type {
2+
FormField,
3+
InkAnnotation,
4+
WidgetAnnotation,
5+
} from "@nutrient-sdk/viewer";
6+
import { baseOptions } from "../../shared/base-options";
7+
8+
interface Size {
9+
width: number;
10+
height: number;
11+
}
12+
13+
window.NutrientViewer.load({
14+
...baseOptions,
15+
theme: window.NutrientViewer.Theme.DARK,
16+
}).then(async (instance) => {
17+
let storedSignature: InkAnnotation | null = null;
18+
19+
const formFields = await instance.getFormFields();
20+
21+
instance.addEventListener("annotations.create", (annotations) => {
22+
const annotation = annotations.first();
23+
if (!annotation) return;
24+
25+
if (
26+
annotation instanceof window.NutrientViewer.Annotations.InkAnnotation &&
27+
annotation.isSignature
28+
) {
29+
storedSignature = annotation;
30+
}
31+
});
32+
33+
instance.addEventListener("annotations.press", (event) => {
34+
const widget = event.annotation as WidgetAnnotation;
35+
const { id } = widget;
36+
37+
const isWidgetSignature = formFields.some((form: FormField) => {
38+
if (
39+
form instanceof window.NutrientViewer.FormFields.SignatureFormField &&
40+
form.annotationIds.includes(id)
41+
) {
42+
return true;
43+
}
44+
return false;
45+
});
46+
47+
if (!storedSignature || !isWidgetSignature) return;
48+
49+
event.preventDefault?.();
50+
instance.create(translateInkAnnotation(storedSignature, widget));
51+
});
52+
53+
function translateInkAnnotation(
54+
annotation: InkAnnotation,
55+
widget: WidgetAnnotation,
56+
) {
57+
const newSize = fitIn(
58+
{
59+
width: annotation.boundingBox.width,
60+
height: annotation.boundingBox.height,
61+
},
62+
{
63+
width: widget.boundingBox.width,
64+
height: widget.boundingBox.height,
65+
},
66+
);
67+
68+
const newLeft =
69+
widget.boundingBox.left +
70+
widget.boundingBox.width / 2 -
71+
newSize.width / 2;
72+
const newTop =
73+
widget.boundingBox.top +
74+
widget.boundingBox.height / 2 -
75+
newSize.height / 2;
76+
77+
const newBoundingBox = new window.NutrientViewer.Geometry.Rect({
78+
left: newLeft,
79+
top: newTop,
80+
width: newSize.width,
81+
height: newSize.height,
82+
});
83+
84+
return annotation
85+
.set("id", window.NutrientViewer.generateInstantId())
86+
.set("pageIndex", widget.pageIndex)
87+
.set("boundingBox", newBoundingBox);
88+
}
89+
90+
function fitIn(size: Size, containerSize: Size): Size {
91+
const { width, height } = size;
92+
93+
const widthRatio = containerSize.width / width;
94+
const heightRatio = containerSize.height / height;
95+
96+
const ratio = Math.min(widthRatio, heightRatio);
97+
98+
return {
99+
width: width * ratio,
100+
height: height * ratio,
101+
};
102+
}
103+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: signatures
3+
title: Reuse Signature in Form Fields
4+
description: Stores a drawn signature and allows placing it into signature form field widgets by clicking on them, automatically scaling to fit.
5+
keywords: [signature, form-field, ink-annotation, widget, reuse]
6+
---

0 commit comments

Comments
 (0)