Terra Draw

Use Terra Draw to draw a geometry in various forms such as point, line or polygon on your map.

<script lang="ts">
  import { MapLibre, GlobeControl } from 'svelte-maplibre-gl';
  import { TerraDraw } from 'svelte-maplibre-gl/terradraw';
  import type { TerraDraw as Draw } from 'terra-draw';
  import {
    TerraDrawCircleMode,
    TerraDrawRectangleMode,
    TerraDrawFreehandMode,
    TerraDrawAngledRectangleMode,
    TerraDrawLineStringMode,
    TerraDrawPolygonMode,
    TerraDrawPointMode,
    TerraDrawSectorMode,
    TerraDrawSelectMode,
    TerraDrawSensorMode
  } from 'terra-draw';

  const defaultSelectFlags = {
    feature: {
      draggable: true,
      coordinates: {
        deletable: true,
        midpoints: true,
        draggable: true
      }
    }
  };
  const modes = [
    new TerraDrawSelectMode({
      flags: {
        point: defaultSelectFlags,
        linestring: defaultSelectFlags,
        polygon: defaultSelectFlags,
        freehand: defaultSelectFlags,
        circle: defaultSelectFlags,
        rectangle: defaultSelectFlags,
        sector: defaultSelectFlags,
        sensor: defaultSelectFlags,
        'angled-rectangle': defaultSelectFlags
      }
    }),
    new TerraDrawPointMode(),
    new TerraDrawLineStringMode(),
    new TerraDrawPolygonMode(),
    new TerraDrawCircleMode(),
    new TerraDrawSectorMode(),
    new TerraDrawSensorMode(),
    new TerraDrawRectangleMode(),
    new TerraDrawFreehandMode(),
    new TerraDrawAngledRectangleMode()
  ];
  const modeNames = modes.map((mode) => mode.mode);
  let mode = $state('select');
  let selected: string | number | null = $state(null);
  let draw: Draw | undefined = $state.raw();
</script>

<MapLibre
  class="h-[55vh] min-h-[300px]"
  style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
  zoom={2}
  center={{ lng: 60, lat: 20 }}
>
  <!-- Terra Draw -->
  <TerraDraw
    {mode}
    {modes}
    bind:draw
    onselect={(featureId) => (selected = featureId)}
    ondeselect={() => (selected = null)}
    onfinish={() => (mode = 'select')}
  />

  <!-- Draw controls -->
  <div
    class="absolute top-3 left-3 z-10 flex flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
  >
    {#each modeNames as modeName}
      <label><input type="radio" bind:group={mode} value={modeName} class="mr-1" /> {modeName}</label>
    {/each}
    {#if selected}
      <button
        class="mt-1 rounded border px-1"
        onclick={() => {
          if (!selected) return;
          draw?.removeFeatures([selected]);
          draw?.deselectFeature(selected);
        }}>Remove</button
      >
    {/if}
  </div>
  <GlobeControl />
</MapLibre>
Our examples use Tailwind CSS and shadcn-svelte.