> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/annotation/customize/customize-rendering.md).

# Customize Annotation Rendering

Customize annotation rendering in WebViewer using setCustomDrawHandler API. Change how annotations are visually represented on screen for both standard and custom annotations. The Apryse Web SDK strea

The PDF specification provides the definition of a standard set of annotations, but not how they are visually represented on screen as that is left to the document viewers. WebViewer allows changing how annotations are rendered when viewing them using the [setCustomDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.setCustomDrawHandler) API. This can be applied to both standard and custom annotations in WebViewer.

If you are using [custom annotations](/web/annotation/customize/creating-custom-annotations.md), they already have support for custom rendering. However, implementing one may be too much if you only want to change how annotations look, especially the standard set. This API will allow you to change how the annotations render without having to implement one.

{% hint style="info" %}
The APIs in this guide are only available in WebViewer 7.1+.
{% endhint %}

## Changing annotation rendering

To change how annotations are rendered, you can use the [setCustomDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.setCustomDrawHandler) API.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
Annotations.setCustomDrawHandler(Annotations.RectangleAnnotation, function(ctx, pageMatrix, rotation, options) {
    options.originalDraw(ctx, pageMatrix, rotation);
    ctx.save();
    ctx.fillStyle = '#000000';
    ctx.fillText('Hello', this.X, this.Y + 12);
    ctx.restore();
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

[Annotations.setCustomDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.setCustomDrawHandler)

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-51b093e121429d4efa3bd25fb400837eb98ddd6e%2F056b1f8d3383436a1309125dccf96f2402bdeaba-226x211.png?alt=media)

### Draw handler function

Alongside the annotation class you are targeting, you must provide a new, custom [draw function](https://sdk.apryse.com/api/web/Core.Annotations.html#.CustomAnnotationDrawHandler) to the API that will perform the rendering. It takes the regular parameters you would expect from an annotation [`draw`](https://sdk.apryse.com/api/web/Core.Annotations.Annotation.html#draw) function with an additional `options` parameter. If you are using an arrow function (bound function), then you can find the annotation through the `options` parameter.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
// Draw handler signature
function(ctx, pageMatrix, rotation, options) {
  ...
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

[CustomAnnotationDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.CustomAnnotationDrawHandler)

Note that you get the annotation being drawn as well as the original annotation's draw function as part of the `options` parameter. This allows you to reference the annotation and perform the original draw if necessary.

### Appearances

Although this works with annotations in WebViewer, other viewers will render the annotations according to how they render the annotations. By default, [setCustomDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.setCustomDrawHandler) will generate an appearance for the annotation so it will look similar in other viewers. If you want to turn this off, perhaps for changing rendering at certain times or it's unnecessary, you can set the `generateAppearance` option in the third parameter of the API.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
Annotations.setCustomDrawHandler(Annotations.RectangleAnnotation, function(ctx, pageMatrix, rotation, options) {
    ...
}, {
  generateAppearance: false,
  canvasMultiplier: 2, // Increase appearance quality at the cost of memory
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Restoring custom annotation rendering

When customizing annotation rendering, the original draw function is preserved. Calling the [setCustomDrawHandler](https://sdk.apryse.com/api/web/Core.Annotations.html#.setCustomDrawHandler) API again will not overwrite the original draw function. This allows the original behavior of the annotation to be restored with [restoreDraw](https://sdk.apryse.com/api/web/Core.Annotations.html#.restoreDraw) API.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
Annotations.restoreDraw(Annotations.RectangleAnnotation);
```

{% endcode %}
{% endtab %}
{% endtabs %}

[Annotations.restoreDraw](https://sdk.apryse.com/api/web/Core.Annotations.html#.restoreDraw)

## Next steps

Check out how to [customize](/web/annotation/customize/customize-serialization.md) the serialization/deserialization behavior of annotations to save your custom properties.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/annotation/customize/customize-rendering.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
