|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Squiggly annotation in TypeScript PDF Viewer | Syncfusion |
| 4 | +description: Learn to add, edit, delete, and customize Squiggly text markup annotations in Syncfusion TypeScript PDF Viewer, with UI and programmatic examples. |
| 5 | +platform: document-processing |
| 6 | +control: PDF Viewer |
| 7 | +documentation: ug |
| 8 | +domainurl: ##DomainURL## |
| 9 | +--- |
| 10 | + |
| 11 | +# Squiggly annotation in TypeScript PDF Viewer |
| 12 | + |
| 13 | +The PDF Viewer provides options to add, edit, and delete Squiggly text markup annotations on text. You can add squigglies via the UI (context menu or annotation toolbar) and programmatically. You can also customize color, opacity, author/subject, and default settings, and use undo/redo, save, print, or disable them as needed. |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +## Add Squiggly Annotation |
| 18 | + |
| 19 | +### Add squiggly annotation in UI |
| 20 | + |
| 21 | +You can add squiggly annotations in two ways: |
| 22 | + |
| 23 | +1. Using the context menu |
| 24 | +* Select text in the PDF document and right-click it. |
| 25 | +* Choose **Squiggly** in the context menu. |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +2. Using the annotation toolbar |
| 30 | +* Click the **Edit Annotation** button in the PDF Viewer toolbar to open the annotation toolbar. |
| 31 | +* Select **Squiggly** to enable squiggly mode. |
| 32 | +* Select text to add the squiggly annotation. |
| 33 | +* Alternatively, select text first and then click **Squiggly**. |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +N> When in pan mode, selecting a text markup annotation switches the PDF Viewer to text select mode. |
| 38 | + |
| 39 | +Enable/exit squiggly mode using the following code: |
| 40 | + |
| 41 | +```html |
| 42 | +<button id="squigglyMode">Squiggly</button> |
| 43 | +<button id="setNone">Normal Mode</button> |
| 44 | +``` |
| 45 | +{% tabs %} |
| 46 | +{% highlight ts tabtitle="Standalone" %} |
| 47 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer } from '@syncfusion/ej2-pdfviewer'; |
| 48 | + |
| 49 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 50 | + |
| 51 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 52 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 53 | +pdfviewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib"; |
| 54 | +pdfviewer.appendTo('#PdfViewer'); |
| 55 | + |
| 56 | +document.getElementById('squigglyMode')?.addEventListener('click', () => { |
| 57 | + pdfviewer.annotation.setAnnotationMode('Squiggly'); |
| 58 | +}); |
| 59 | + |
| 60 | +document.getElementById('setNone')?.addEventListener('click', () => { |
| 61 | + pdfviewer.annotation.setAnnotationMode('None'); |
| 62 | +}); |
| 63 | +{% endhighlight %} |
| 64 | +{% highlight ts tabtitle="Server-Backed" %} |
| 65 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer } from '@syncfusion/ej2-pdfviewer'; |
| 66 | + |
| 67 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 68 | + |
| 69 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 70 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 71 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 72 | +pdfviewer.appendTo('#PdfViewer'); |
| 73 | + |
| 74 | +document.getElementById('squigglyMode')?.addEventListener('click', () => { |
| 75 | + pdfviewer.annotation.setAnnotationMode('Squiggly'); |
| 76 | +}); |
| 77 | + |
| 78 | +document.getElementById('setNone')?.addEventListener('click', () => { |
| 79 | + pdfviewer.annotation.setAnnotationMode('None'); |
| 80 | +}); |
| 81 | +{% endhighlight %} |
| 82 | +{% endtabs %} |
| 83 | + |
| 84 | +### Add squiggly annotation programmatically |
| 85 | + |
| 86 | +Add squiggly annotations programmatically using the [addAnnotation](https://ej2.syncfusion.com/documentation/api/pdfviewer/annotation/#addannotation) method. |
| 87 | + |
| 88 | +```html |
| 89 | +<button id="addSquiggly">Add Squiggly annotation programmatically</button> |
| 90 | +``` |
| 91 | +{% tabs %} |
| 92 | +{% highlight ts tabtitle="Standalone" %} |
| 93 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer, SquigglySettings } from '@syncfusion/ej2-pdfviewer'; |
| 94 | + |
| 95 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 96 | + |
| 97 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 98 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 99 | +pdfviewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib"; |
| 100 | +pdfviewer.appendTo('#PdfViewer'); |
| 101 | + |
| 102 | +document.getElementById('addSquiggly')?.addEventListener('click', () => { |
| 103 | + pdfviewer.annotation.addAnnotation('Squiggly', { |
| 104 | + bounds: [{ x: 97, y: 110, width: 350, height: 14 }], |
| 105 | + pageNumber: 1 |
| 106 | + } as SquigglySettings); |
| 107 | +}); |
| 108 | +{% endhighlight %} |
| 109 | +{% highlight ts tabtitle="Server-Backed" %} |
| 110 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer, SquigglySettings } from '@syncfusion/ej2-pdfviewer'; |
| 111 | + |
| 112 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 113 | + |
| 114 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 115 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 116 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 117 | +pdfviewer.appendTo('#PdfViewer'); |
| 118 | + |
| 119 | +document.getElementById('addSquiggly')?.addEventListener('click', () => { |
| 120 | + pdfviewer.annotation.addAnnotation('Squiggly', { |
| 121 | + bounds: [{ x: 97, y: 110, width: 350, height: 14 }], |
| 122 | + pageNumber: 1 |
| 123 | + } as SquigglySettings); |
| 124 | +}); |
| 125 | +{% endhighlight %} |
| 126 | +{% endtabs %} |
| 127 | + |
| 128 | +## Edit Squiggly Annotation |
| 129 | + |
| 130 | +### Edit squiggly annotation in UI |
| 131 | + |
| 132 | +You can select and delete squiggly annotations directly in the viewer. Use the context menu or toolbar options as needed. |
| 133 | + |
| 134 | +Delete the selected annotation in the following ways: |
| 135 | + |
| 136 | +1. Using the Delete/Backspace key |
| 137 | + * Select the annotation. |
| 138 | + * Press Delete (or Backspace). The selected annotation is removed. |
| 139 | + |
| 140 | +2. Using the annotation toolbar |
| 141 | + * Select the annotation. |
| 142 | + * Click **Delete Annotation** in the annotation toolbar. The selected annotation is removed. |
| 143 | + |
| 144 | + |
| 145 | + |
| 146 | +#### Edit squiggly annotation properties in UI |
| 147 | + |
| 148 | +The color and opacity of the squiggly annotation can be edited using the Edit Color and Edit Opacity tools in the annotation toolbar. |
| 149 | + |
| 150 | +- Edit color: Use the color palette in the Edit Color tool to change the annotation color. |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | +- Edit opacity: Use the range slider in the Edit Opacity tool to change annotation opacity. |
| 155 | + |
| 156 | + |
| 157 | + |
| 158 | +### Edit a squiggly annotation programmatically |
| 159 | + |
| 160 | +To modify an existing squiggly annotation programmatically, use the editAnnotation() method. |
| 161 | + |
| 162 | +```html |
| 163 | +<button id="editSquiggly">Edit Squiggly annotation programmatically</button> |
| 164 | +``` |
| 165 | + |
| 166 | +{% tabs %} |
| 167 | +{% highlight ts tabtitle="Standalone" %} |
| 168 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer } from '@syncfusion/ej2-pdfviewer'; |
| 169 | + |
| 170 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 171 | + |
| 172 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 173 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 174 | +pdfviewer.resourceUrl = "https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib"; |
| 175 | +pdfviewer.appendTo('#PdfViewer'); |
| 176 | + |
| 177 | +document.getElementById('editSquiggly')?.addEventListener('click', () => { |
| 178 | + for (let i = 0; i < pdfviewer.annotationCollection.length; i++) { |
| 179 | + const ann = pdfviewer.annotationCollection[i]; |
| 180 | + if (ann.author === 'Guest User' || ann.subject === 'Corrections') { |
| 181 | + ann.color = '#ff0000'; |
| 182 | + ann.opacity = 0.8; |
| 183 | + pdfviewer.annotation.editAnnotation(ann); |
| 184 | + } |
| 185 | + } |
| 186 | +}); |
| 187 | +{% endhighlight %} |
| 188 | +{% highlight ts tabtitle="Server-Backed" %} |
| 189 | +import { PdfViewer, Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer } from '@syncfusion/ej2-pdfviewer'; |
| 190 | + |
| 191 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, Annotation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, TextSearch, FormFields, FormDesigner, PageOrganizer); |
| 192 | + |
| 193 | +let pdfviewer: PdfViewer = new PdfViewer(); |
| 194 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 195 | +pdfviewer.documentPath = "https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"; |
| 196 | +pdfviewer.appendTo('#PdfViewer'); |
| 197 | + |
| 198 | +document.getElementById('editSquiggly')?.addEventListener('click', () => { |
| 199 | + for (let i = 0; i < pdfviewer.annotationCollection.length; i++) { |
| 200 | + const ann = pdfviewer.annotationCollection[i]; |
| 201 | + if (ann.author === 'Guest User' || ann.subject === 'Corrections') { |
| 202 | + ann.color = '#ff0000'; |
| 203 | + ann.opacity = 0.8; |
| 204 | + pdfviewer.annotation.editAnnotation(ann); |
| 205 | + } |
| 206 | + } |
| 207 | +}); |
| 208 | +{% endhighlight %} |
| 209 | +{% endtabs %} |
| 210 | + |
| 211 | +## Set default properties during control initialization |
| 212 | + |
| 213 | +Set default properties before creating the control using `squigglySettings`. |
| 214 | + |
| 215 | +> After editing default color and opacity using the Edit Color and Edit Opacity tools, the values update to the selected settings. |
| 216 | +
|
| 217 | +{% tabs %} |
| 218 | +{% highlight ts tabtitle="Standalone" %} |
| 219 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation } from '@syncfusion/ej2-pdfviewer'; |
| 220 | + |
| 221 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation); |
| 222 | + |
| 223 | +let pdfviewer: PdfViewer = new PdfViewer({ |
| 224 | + documentPath: 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf', |
| 225 | + squigglySettings: { author: 'Guest User', subject: 'Corrections', color: '#00ff00', opacity: 0.9} |
| 226 | +}); |
| 227 | +pdfviewer.appendTo('#PdfViewer'); |
| 228 | +{% endhighlight %} |
| 229 | +{% highlight ts tabtitle="Server-Backed" %} |
| 230 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation } from '@syncfusion/ej2-pdfviewer'; |
| 231 | + |
| 232 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation); |
| 233 | + |
| 234 | +let pdfviewer: PdfViewer = new PdfViewer({ |
| 235 | + documentPath: 'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf', |
| 236 | + squigglySettings: { author: 'Guest User', subject: 'Corrections', color: '#00ff00', opacity: 0.9} |
| 237 | +}); |
| 238 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 239 | +pdfviewer.appendTo('#PdfViewer'); |
| 240 | +{% endhighlight %} |
| 241 | +{% endtabs %} |
| 242 | + |
| 243 | +## Perform undo and redo |
| 244 | + |
| 245 | +The PDF Viewer supports undo and redo for squiggly annotations: |
| 246 | + |
| 247 | +* Adding squiggly annotations |
| 248 | +* Deleting squiggly annotations |
| 249 | +* Changing color or opacity |
| 250 | + |
| 251 | +Undo and redo actions can be performed in the following ways: |
| 252 | + |
| 253 | +1. Using keyboard shortcuts: |
| 254 | + After a squiggly annotation action, press Ctrl+Z to undo and Ctrl+Y to redo. |
| 255 | +2. Using the toolbar: |
| 256 | + Use the **Undo** and **Redo** tools in the toolbar. |
| 257 | + |
| 258 | +{% tabs %} |
| 259 | +{% highlight ts tabtitle="Standalone" %} |
| 260 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation, FormDesigner, FormFields } from '@syncfusion/ej2-pdfviewer'; |
| 261 | + |
| 262 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation, FormDesigner, FormFields); |
| 263 | + |
| 264 | +let pdfviewer: PdfViewer = new PdfViewer({ |
| 265 | + documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf', |
| 266 | + resourceUrl:"https://cdn.syncfusion.com/ej2/31.1.23/dist/ej2-pdfviewer-lib" |
| 267 | +}); |
| 268 | +pdfviewer.appendTo('#PdfViewer'); |
| 269 | + |
| 270 | +document.getElementById('undo')?.addEventListener('click', ()=> { |
| 271 | + pdfviewer.undo(); |
| 272 | +}); |
| 273 | + |
| 274 | +document.getElementById('redo')?.addEventListener('click', ()=> { |
| 275 | + pdfviewer.redo(); |
| 276 | +}); |
| 277 | +{% endhighlight %} |
| 278 | +{% highlight ts tabtitle="Server-Backed" %} |
| 279 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation, FormDesigner, FormFields } from '@syncfusion/ej2-pdfviewer'; |
| 280 | + |
| 281 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation, FormDesigner, FormFields); |
| 282 | + |
| 283 | +let pdfviewer: PdfViewer = new PdfViewer({ |
| 284 | + documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf' |
| 285 | +}); |
| 286 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 287 | +pdfviewer.appendTo('#PdfViewer'); |
| 288 | + |
| 289 | +document.getElementById('undo')?.addEventListener('click', ()=> { |
| 290 | + pdfviewer.undo(); |
| 291 | +}); |
| 292 | + |
| 293 | +document.getElementById('redo')?.addEventListener('click', ()=> { |
| 294 | + pdfviewer.redo(); |
| 295 | +}); |
| 296 | +{% endhighlight %} |
| 297 | +{% endtabs %} |
| 298 | + |
| 299 | +## Disable squiggly annotation |
| 300 | + |
| 301 | +Disable text markup annotations (including squiggly) using the `enableTextMarkupAnnotation` property. |
| 302 | + |
| 303 | +{% tabs %} |
| 304 | +{% highlight ts tabtitle="Standalone" %} |
| 305 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation } from '@syncfusion/ej2-pdfviewer'; |
| 306 | + |
| 307 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation); |
| 308 | + |
| 309 | +let pdfviewer: PdfViewer = new PdfViewer({ documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf', enableTextMarkupAnnotation: false }); |
| 310 | +pdfviewer.appendTo('#PdfViewer'); |
| 311 | +{% endhighlight %} |
| 312 | +{% highlight ts tabtitle="Server-Backed" %} |
| 313 | +import { PdfViewer, Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation } from '@syncfusion/ej2-pdfviewer'; |
| 314 | + |
| 315 | +PdfViewer.Inject(Toolbar, Magnification, Navigation, LinkAnnotation, ThumbnailView, BookmarkView, TextSelection, Annotation); |
| 316 | + |
| 317 | +let pdfviewer: PdfViewer = new PdfViewer({ documentPath:'https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf', enableTextMarkupAnnotation: false }); |
| 318 | +pdfviewer.serviceUrl = 'https://document.syncfusion.com/web-services/pdf-viewer/api/pdfviewer/'; |
| 319 | +pdfviewer.appendTo('#PdfViewer'); |
| 320 | +{% endhighlight %} |
| 321 | +{% endtabs %} |
| 322 | + |
| 323 | +[View Sample on GitHub](https://github.com/SyncfusionExamples/typescript-pdf-viewer-examples/tree/master) |
0 commit comments