Skip to content

Latest commit

 

History

History
397 lines (322 loc) · 10.5 KB

3.ADAPTERS.md

File metadata and controls

397 lines (322 loc) · 10.5 KB

Adapters

Adapters are the layer between the core of the library and the external mapping libraries (Leaflet, Google Maps etc).

In simple terms an adapter takes input events, passes them through to create geometries in the store and then passes them back to the Adapter to be rendered specifically for the mapping library.

Available Adapters

Terra Draw comes with a set of built in Adapters that you can use out of the box:

Provider Requires API Key Class Jump to
Leaflet No TerraDrawLeafletAdapter Example
MapLibre No TerraDrawMapLibreGLAdapter Example
OpenLayers No TerraDrawOpenLayersAdapter Example
Google Maps Yes TerraDrawGoogleMapsAdapter Example
Mapbox Yes TerraDrawMapboxGLAdapter Example
ArcGIS Maps Yes TerraDrawArcGISMapsSDKAdapter

Using an Adapter

Each Adapter must be instantiated with the library map instance (using the map property) and the map library itself (using the lib property). This is so that Terra Draw can access the map library API without having to import it directly.

For TerraDrawMapLibreGLAdapter for example:

// Import MapLibre Library
import maplibregl from "maplibre-gl";

// Create Map Instance
const map = new maplibregl.Map({
  container: id,
  style: 'https://demotiles.maplibre.org/style.json',
  center: [lng, lat],
  zoom: zoom,
});

// Create Adapter
const adapter = new TerraDrawMapLibreGLAdapter({
  // Pass in the map instance
  map,
});

To use an Adapter you need to pass it to the Terra Draw constructor using the adapter property:

const draw = new TerraDraw({
  adapter: adapter,
  modes: [new TerraDrawRectangleMode()],
});

Important

Each Adapter must be instantiated with both map and lib properties.

Examples

Code examples for each of the available Adapters are provided below.

Prerequisites

The following examples assumes that the both Terra Draw and the relevant mapping library have been added to your project using a package manager (i.e. NPM) that includes a build step (e.g. Webpack, Vite etc):

npm install terra-draw
npm install leaflet

Your HTML needs to contain a <div> element with an id of map, where the map will be rendered:

<div id="map"></div>

Tip

This container, with an id of "map" is assumed to be present in all examples throughout the documentation.

The following code samples rely on some configuration values being defined. For example:

// Target element id
const id = "map";

// Initial longitude and latitude
const lng = -1.826252;
const lat = 51.179026;

// Initial zoom level
const zoom = 16;

Tip

See the Installation section for more information, including a full example of using Terra Draw without a build step.

Leaflet

//Import Leaflet
import * as L from "leaflet";
import "leaflet/dist/leaflet.css";

// Import Terra Draw
import {
  TerraDraw,
  TerraDrawLeafletAdapter,
  TerraDrawFreehandMode,
} from "terra-draw";

// Create Map
const map = L.map(id, {
  center: [lat, lng],
  zoom: zoom,
});

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution:
    '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);

// Create Terra Draw
const draw = new TerraDraw({
  adapter: new TerraDrawLeafletAdapter({
    lib: L,
    map,
  }),
  modes: [new TerraDrawFreehandMode()],
});

// Start drawing
draw.start();
draw.setMode("freehand");

MapLibre

// Import MapLibre
import MapLibreGL from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";

// Import Terra Draw
import {
  TerraDraw,
  TerraDrawMapLibreGLAdapter,
  TerraDrawFreehandMode,
} from "terra-draw";

// Create Map
const map = new MapLibreGL.Map({
  container: id,
  style: {
    version: 8,
    sources: {
      "osm-tiles": {
        type: "raster",
        tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
        tileSize: 256,
        attribution:
          '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      },
    },
    layers: [
      {
        id: "osm-tiles",
        type: "raster",
        source: "osm-tiles",
      },
    ],
  },
  center: [lng, lat],
  zoom: zoom,
});

// Create Terra Draw
const draw = new TerraDraw({
  adapter: new TerraDrawMapLibreGLAdapter({
    map,
  }),
  modes: [new TerraDrawFreehandMode()],
});

// Start drawing
draw.start();
draw.setMode("freehand");

Google Maps

Important

There are some requirements for the Google Map Adapter to work correctly:

  1. The Google Maps API requires an apiKey property when loading the library.
  2. The map element must have a id property set
  3. Because an OverlayView is created, which can only be done asynchronously, you must wait for the 'ready' event on the draw instance
// Import Google Maps
import { Loader } from "@googlemaps/js-api-loader";

// Import Terra Draw
import {
  TerraDraw,
  TerraDrawGoogleMapsAdapter,
  TerraDrawFreehandMode,
} from "terra-draw";

// API key required
const apiKey = "<your_api_key>";

// Load Google Maps
const loader = new Loader({
  apiKey,
  version: "weekly",
});

loader.load().then((google) => {
  // Create map element
  const mapElement = document.getElementById(id) // The map element must have an id set for the adapter to work!

  // Create the google map itself
  const map = new google.maps.Map(mapElement, {
    disableDefaultUI: true,
    center: { lat, lng },
    zoom: zoom,
    clickableIcons: false,
  });

  // Once the map is loaded
  map.addListener("projection_changed", () => {
    // Create Terra Draw
    const draw = new TerraDraw({
      adapter: new TerraDrawGoogleMapsAdapter({
        lib: google.maps,
        map,
        coordinatePrecision: 9,
      }),
      modes: [new TerraDrawFreehandMode()],
    });

    // Start drawing
    draw.start();

    // Unlike other adapters, the google adapter 'ready' event is required to be listened for
    // because the adapter creates an OverlayView which is only ready asynchronously
    draw.on('ready', () => {
      draw.setMode("freehand");
    })
  });
});

OpenLayers

import {
    TerraDraw,
    TerraDrawFreehandMode,
    TerraDrawOpenLayersAdapter,
} from "terra-draw";

import Feature from "ol/Feature";
import GeoJSON from "ol/format/GeoJSON";
import Map from "ol/Map";
import View from "ol/View";
import { Circle, Stroke, Style } from "ol/style";
import { OSM, Vector as VectorSource } from "ol/source";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { fromLonLat, getUserProjection } from "ol/proj";

// Create map
const map = new Map({
    layers: [
        new TileLayer({
            source: new OSM(),
        }),
    ],
    target: 'map',
    view: new View({
        center: fromLonLat([0, 0]),
        zoom: 2,
    }),
    controls: [],
});

map.once("postrender", () => {
    // Create Terra Draw
    const draw = new TerraDraw({
        adapter: new TerraDrawOpenLayersAdapter({
            lib: {
             	Feature,
              GeoJSON,
              Style,
              VectorLayer,
              VectorSource,
              Stroke,
              getUserProjection,
              Circle,
              Fill,
            },
            map,
            coordinatePrecision: 9,
        }),
        modes: [new TerraDrawFreehandMode()],
    });

    // Start drawing
    draw.start();
    draw.setMode("freehand");
});

Mapbox

Important

MapboxGL JS requires an API key to be set in the mapboxgl.accessToken property.

// Import MapBox GL
import mapboxgl from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";

// Import Terra Draw
import {
  TerraDraw,
  TerraDrawMapboxGLAdapter,
  TerraDrawFreehandMode,
} from "terra-draw";

// API key required
const apiKey = "<your_access_token>";

// Create Map
mapboxgl.accessToken = apiKey;
const map = new mapboxgl.Map({
  container: id,
  style: {
    version: 8,
    sources: {
      "osm-tiles": {
        type: "raster",
        tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
        tileSize: 256,
        attribution:
          '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      },
    },
    layers: [
      {
        id: "osm-tiles",
        type: "raster",
        source: "osm-tiles",
      },
    ],
  },
  center: [lng, lat],
  zoom: zoom,
});

// Create Terra Draw
const draw = new TerraDraw({
  adapter: new TerraDrawMapboxGLAdapter({
    map,
  }),
  modes: [new TerraDrawFreehandMode()],
});

// Start drawing
draw.start();
draw.setMode("freehand");

Creating Custom Adapters

See the Development guide for more information on creating custom Adapters.


Guides

  1. Getting Started
  2. Store
  3. Adapters
  4. Modes
  5. Styling
  6. Events
  7. Development
  8. Examples