# Drawing annotations

{% hint style="warning" %}

#### Note: Annotations were previously referred to as Elements.

References have been updated in the app and documentation, while naming in the REST API and JS SDK remains unchanged.
{% endhint %}

The Felt SDK provides two main approaches for creating annotations on your maps:

1. **Interactive Drawing**: Configure and activate drawing tools for users to create annotations manually
2. **Programmatic Creation**: Create and modify annotations directly through code

Annotations created via the SDK are session-specific - they're not persisted to the map and won't be visible to other users.

## Interactive Drawing with Tools

The methods on the [`ToolsController`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller) enable you to programmatically activate drawing tools for your users, as well as setting various options for the tools, such as color, line width, etc.

Use the [`setTool`](https://developers.felt.com/js-sdk/broken-reference) method to activate a particular tool.

Use the [`setToolSettings`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller#settoolsettings) method to configure the options for a specific tool.

Use the [`onToolChange`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller#ontoolchange) and [`onToolSettingsChange`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller#ontoolsettingschange) to be notified of changes to the above, or read them instantaneously with the [`getTool`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller#gettool) and [`getToolSettings`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/tools/toolscontroller#gettoolsettings) methods.

As the user creates annotations with the tools, you can be notified of them being created and updated using the [`onElementCreate`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementcreate) and [`onElementChange`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementchange) listeners. See [#listening-for-annotation-creation](#listening-for-annotation-creation "mention") for more details.

### Tool types

<table><thead><tr><th width="166.3798828125">Tool name</th><th width="232.486328125">Annotation Type</th><th>Description</th></tr></thead><tbody><tr><td><code>pin</code></td><td>Place</td><td>Creates a single point on a map, with a symbol and optional label</td></tr><tr><td><code>line</code></td><td>Line</td><td>Creates a sequence of straight lines through the points that the user clicks</td></tr><tr><td><code>route</code></td><td>Line</td><td>Creates a line that follows the routing logic depending on the mode of transport selected. For instance, walking, driving and cycling routes follow applicable roads and pathways to reach the waypoints the user provides. Flying routes follow great circle paths.</td></tr><tr><td><code>polygon</code></td><td>Polygon</td><td>Creates an enclosed area with straight edges</td></tr><tr><td><code>circle</code></td><td>Circle</td><td>A circle is defined by its center and radius.</td></tr><tr><td><code>marker</code></td><td>Marker</td><td>Freeform drawing with a pen-like rendering. Different sizes can be set for the pen. The geometry produced is in world-space, so as you zoom the map, the pen strokes remain in place.</td></tr><tr><td><code>highlighter</code></td><td>Highlighter</td><td>Represents an area of interest, created by drawing with a thick pen. By default, drawing an enclosed shape fills the interior.</td></tr><tr><td><code>text</code></td><td>Text</td><td>A label placed on the map with no background color.</td></tr><tr><td><code>note</code></td><td>Note</td><td>A label placed on the map with a rectangular background color and either white or black text.</td></tr></tbody></table>

### Example

```javascript
// Configure the line tool
felt.setToolSettings({
  tool: "line",
  strokeWidth: 8,
  color: "#448C2A"
});

// Activate the line tool
felt.setTool("line");

// Later, deactivate the tool
felt.setTool(null);
```

## Programmatic Annotation Creation

If you want to create annotations programmatically instead of letting your users draw them interactively on the map, use the methods in the [`ElementsController`](https://developers.felt.com/js-sdk/broken-reference).

To create annotations, use the [`createElement`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#createelement) method.

To update annotations, use the [`updateElement`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#updateelement) method.

To delete annotations, use the [`deleteElement`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#deleteelement) method.

When annotations are created programatically, they also trigger notifications about the corresponding changes to annotations, via `onElementCreate`, `onElementChange` and `onElementDelete`.

### Example

```javascript

// Create a polygon
const polygonElement = await felt.createElement({
  type: "Polygon",
  coordinates: [
    [
      [-122.42, 37.78],
      [-122.41, 37.78],
      [-122.41, 37.77],
      [-122.42, 37.77],
      [-122.42, 37.78]
    ]
  ],
  color: "#FF5733",
  fillOpacity: 0.5
});
​

// Update its properties
await felt.updateElement({
  id: polygonElement.id,
  
  // note that we pass the type here, too in order to get correct
  // TypeScript type-checking and autocompletion.
  type: "Polygon",
  
  color: "#ABC123",
  fillOpacity: 0.5,
  strokeWidth: 2
});

// Finally delete the element
await felt.deleteElement(polygonElement.id)
```

## Retrieving Annotation geometry <a href="#getting-elements" id="getting-elements"></a>

Extract the geometric representation of annotations using the [`getElementGeometry`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#getelementgeometry) method.

The geometry is returned in GeoJSON geometry format, which can be quite different to the way the annotation is specified in Felt. For example, `Circle` annotations in Felt have their geometry converted into a polygon, representing the area covered by the circle.

**Note:** Text, Note, and Image annotations do not return geometry as they are considered to annotations rather than true "geospatial" annotations.

```javascript
// Get an element's geometry in GeoJSON format
const geometry = await felt.getElementGeometry("element-1");
console.log(geometry?.type, geometry?.coordinates);
```

## Listening for changes

Every change that is made to the annotations on a map results in a call to either [`onElementCreate`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementcreate), [`onElementDelete`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementdelete) or [`onElementChange`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementchange).

```javascript
// Set up a listener for changes to a polygon
const unsubscribeChange = felt.onElementChange({
  options: { id: polygon.id },
  handler: ({element}) => {
    console.log("Polygon was updated:", element);
  }
});
​
// Set up a listener for deletion
const unsubscribeDelete = felt.onElementDelete({
  options: { id: polygon.id },
  handler: () => {
    console.log("Polygon was deleted");
  }
});
​
// Later, clean up listeners
unsubscribeChange();
unsubscribeDelete();
```

### Listening for annotation creation

There are two different ways for listening to annotations being created, and the one you use depends on how the annotation is being created, and at what point you want to know about an annotation's creation.

When the user is creating annotations with tools, they are often created in a number of steps, such as drawing a marker stroke or creating a polygon with many vertices.

When you want to know when the user has *finished* creating the annotation (e.g. the polygon was closed or the marker stroke ended) then you should use the [`onElementCreateEnd`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementcreateend) listener.

When annotations are created programmatically, they do not trigger the [`onElementCreateEnd`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementcreateend) event.

Annotations created using Tools *or* [`createElement`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#createelement) will trigger the [`onElementCreate`](https://app.gitbook.com/s/0eksRydsZ8lvtEIxgbY5/elements/elementscontroller#onelementcreate) event, with an extra property stating whether the annotation is still being created.

```javascript
// Listen for any element creation
const unsubscribe = felt.onElementCreate({
  handler: (element) => {
    console.log(`New element created with ID: ${element.id}`);
    
    // Check if the element is still being drawn
    if (element.isBeingCreated) {
      console.log("User is still creating this element");
    }
  }
});

// Or listen for when element creation is completed with a tool
const unsubscribeEnd = felt.onElementCreateEnd({
  handler: ({element}) => {
    console.log(`Element ${element.id} creation finished`);
  }
});

// Later, clean up listeners
unsubscribe();
unsubscribeEnd();
```

## Sample application: sending annotations drawn by users to your backend <a href="#creating-a-dynamic-drawing-interface" id="creating-a-dynamic-drawing-interface"></a>

Here is an example showing the power of the Felt SDK, where in just a few lines of code you can allow your users to draw annotations and have them sent to your own backend systems for persistence or analysis.

Assuming you have embedded your Felt map as described in [getting-started](https://developers.felt.com/js-sdk/getting-started "mention"), and in your own UI you have added a `polygon-tool` button and a `reset-tool` button, all you need is the following:

```javascript
// Set your initial tool settings in a style that suits your application
felt.setToolSettings({
  tool: "polygon",
  strokeWidth: 2,
  color: "#FF5733",
  fillOpacity: 0.3,
});
  
// Activate the tool when the user clicks a button in your UI
​document.getElementById("polygon-tool").addEventListener("click", () => {
  felt.setTool("polygon");
});
​
// Disable the tool when the user clicks a button in your UI
document.getElementById("reset-tool").addEventListener("click", () => {
  felt.setTool(null);
});
​
// Listen for completed polygons
felt.onElementCreateEnd({
  handler: async ({element}) => {
    // get the polygon geometry that the user just drew
    const geometry = await felt.getElementGeometry(element.id);
    
    // send the polygon to your own backend system
    sendToServer(geometry);
  }
});
```
