Skip to main content

Drawing geometric shapes

To draw geometric shapes on the MapGL map, you can use the MapGL Terra Draw plugin. The plugin is an adapter for the Terra Draw JavaScript library.

The library allows you to:

  • Draw basic geometric shapes on the map: points, lines, polygons, circles, rectangles, and others.
  • Customize line width, color of vertices, sides, and fill of geometric shapes.
  • Export a file with created geometries in GeoJSON format.

Getting started

To start using the plugin, follow the steps below:

  1. Install the plugin.
  2. Initialize the plugin.

1. Install the plugin

Using script tag

To install the plugin, add the following lines to your HTML page (after initializing the MapGL):

<script src="https://unpkg.com/terra-draw@1.0.0/dist/terra-draw.umd.js"></script>
<script src="https://unpkg.com/@2gis/mapgl-terra-draw/dist/mapgl-terra-draw.umd.cjs"></script>

Using npm package

If you use npm, you can install the plugin using the @2gis/mapgl-terra-draw package:

npm install @2gis/mapgl-terra-draw

2. Initialize the plugin

To initialize the plugin, use the createTerraDrawWithUI() method.

Using script tag

<html>
<head>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined"
/>
<link
rel="stylesheet"
type="text/css"
href="https://unpkg.com/@2gis/mapgl-terra-draw@0.2.0/dist/mapgl-terra-draw.css"
/>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script src="https://unpkg.com/terra-draw@1.0.0/dist/terra-draw.umd.js"></script>
<script src="https://unpkg.com/@2gis/mapgl-terra-draw/dist/mapgl-terra-draw.umd.cjs"></script>
<style>
html,
body,
#container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
const map = new mapgl.Map('container', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
enableTrackResize: true,
});

map.on('styleload', () => {
mapglTerraDraw.createTerraDrawWithUI({
map,
mapgl: mapgl,
controls: [
'color',
'select',
'point',
'polygon',
'circle',
'download',
'clear',
],
});
});
</script>
</body>
</html>

Using npm package

import { load } from '@2gis/mapgl';
import { createTerraDrawWithUI } from '@2gis/mapgl-terra-draw';
import '@2gis/mapgl-terra-draw/dist/mapgl-terra-draw.css';

load().then((mapgl) => {
const map = new mapgl.Map('map', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
enableTrackResize: true,
});

map.on('styleload', () => {
createTerraDrawWithUI({
map,
mapgl: mapgl as any,
controls: ['color', 'select', 'point', 'polygon', 'circle', 'download', 'clear'],
});
});
});

Usage example

Select the geometry type and click the map to build geometric shapes.

Using the TerraDrawMapGlAdapter

You can use the TerraDrawMapGlAdapter class directly to work with advanced Terra Draw features. For example, to add a mode for selecting objects on the map or to create your own user interface if the built-in one is not suitable for some reason.

An example of creating a map with three drawing modes (selecting objects, drawing points, and drawing polygons) and UI controls for switching modes and deleting drawn objects:

import { load } from '@2gis/mapgl';
import {
TerraDraw,
TerraDrawPointMode,
TerraDrawPolygonMode,
TerraDrawSelectMode,
} from 'terra-draw';
import { TerraDrawMapGlAdapter } from '@2gis/mapgl-terra-draw';

load().then((mapgl) => {
const map = new mapgl.Map('map', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
enableTrackResize: true,
});

map.on('styleload', () => {
const draw = new TerraDraw({
adapter: new TerraDrawMapGlAdapter({
map,
mapgl,
coordinatePrecision: 9,
}),
modes: [
new TerraDrawSelectMode(),
new TerraDrawPointMode(),
new TerraDrawPolygonMode(),
],
});

const buttons = document.createElement('div');
buttons.style.display = 'flex';
buttons.style.flexDirection = 'column';
buttons.style.gap = '8px';
new mapgl.Control(map, buttons, { position: 'centerLeft' });

const selectButton = document.createElement('button');
selectButton.innerText = 'select';
selectButton.addEventListener('click', () => {
draw.setMode('select');
});
buttons.appendChild(selectButton);

const pointButton = document.createElement('button');
pointButton.innerText = 'point';
pointButton.addEventListener('click', () => {
draw.setMode('point');
});
buttons.appendChild(pointButton);

const polygonButton = document.createElement('button');
polygonButton.innerText = 'polygon';
polygonButton.addEventListener('click', () => {
draw.setMode('polygon');
});
buttons.appendChild(polygonButton);

const clearButton = document.createElement('button');
clearButton.innerText = 'clear';
clearButton.addEventListener('click', () => {
draw.clear();
});
buttons.appendChild(clearButton);

draw.start();
});
});

Getting object data

To retrieve data about objects with styles, get the drawn shapes using the getSnapshot() method, create a FeatureCollection object, and add the icons and layers properties to its root:

const adapter = new TerraDrawMapGlAdapter({
...
});
const { draw } = createTerraDrawWithUI({
adapter,
...
});

const features = draw.getSnapshot();
const { icons, layers } = adapter.addStyling(features);
const featureCollection = {
type: 'FeatureCollection',
icons,
layers,
features,
};

To display the obtained data on the map, add icons and layers from the created FeatureCollection to the map using the addIcon() and addLayer() methods, and add GeoJSON as a data source using GeoJsonSource:

for (const icon in featureCollection.icons) {
map.addIcon(icon, { url: featureCollection.icons[icon] });
}
for (const layer of featureCollection.layers) {
map.addLayer(layer);
}
const source = new mapgl.GeoJsonSource(map, {
data: featureCollection,
attributes: {
name: 'terra-draw-output',
},
});

Usage example:

Raw data

If you need to obtain only geometric shapes in GeoJSON format, use the getSnapshot() method of the Terra Draw library:

const { draw } = createTerraDrawWithUI({
...
});

...

draw.getSnapshot();

For more details on adding GeoJSON data to the map, see the GeoJSON instruction.