OpenLayers

Feature Frenzy

[email protected]


[email protected]

New to OpenLayers?


npm install ol

Let's dive in! 🚀

View Animation


view.animate({
  duration: 1500,
  center: [-110, 45],
  rotation: Math.PI / 4,
  zoom: 12
})
    

View Animation


view.animate({
  duration: 1500,
  center: [-110, 45],
  rotation: Math.PI / 4,
  zoom: 12
})
    

Animation Chaining ⛓


view.animate({
  center: london,
  easing: easeIn
}, {
  center: rome,
  easing: easeOut
}, function() {
  // all done
});
    

Use Geographic ⚗️


import {useGeographic} from 'ol/proj';

useGeographic();

// use [longitude, latitude] in API
view.setCenter([-110, 45]);
    

Reprojection


const view = new View({
  projection: custom
});

const source = new VectorSource({
  url: 'https://example.com/world.json',
  format: new GeoJSON()
});
    

Reprojection
(raster too 💪)


const view = new View({
  projection: custom
});

const source = new XYZSource({
  projection: mercator
});
    

GeoTIFF Sources 🎉


import GeoTIFF from 'ol/source/GeoTIFF';

const source = new GeoTIFF({
  sources: [
    {url: 'https://example.com/world.tif'},
  ]
});
    

GeoTIFF Sources 🎉


import GeoTIFF from 'ol/source/GeoTIFF';

const source = new GeoTIFF({
  sources: [
    {url: 'https://example.com/B08.tif'},
    {url: 'https://example.com/B04.tif'},
    {url: 'https://example.com/B02.tif'},
  ]
});
    

Resolving Views 🌱


import GeoTIFF from 'ol/source/GeoTIFF';

const source = new GeoTIFF(options);

const map = new Map({
  target: 'container',
  layers: [new TileLayer({source})],
  view: source.getView(),
});
    

Feature interaction
hit detection


      map.on('pointermove', event => {
        layer
          .getFeatures(event.pixel)
          .then(showProperties);
      });
    

Feature interaction
selection by id


      const selection = new VectorTileLayer({
        source: layer.getSource()
      });

      layer.getFeatures(pixel).then(features => {
        const selected = features.map(f => f.getId());
        selection.setStyle(f =>
          selected.includes(f.getId())
            ? selectStyle
            : null
        );
      });
    

Feature Editing 🔨


import {Draw, Modify, Snap} from 'ol/interaction';

map.addInteraction(
  new Draw({type: 'Polygon', source: source})
);
    

Feature Editing 🔨


import {Draw, Modify, Snap} from 'ol/interaction';

map.addInteraction(
  new Modify({source: source})
);
    

Feature Editing 🔨


import {Draw, Modify, Snap} from 'ol/interaction';

map.addInteraction(
  new Snap({source: source})
);
    

Vector tiles


import MapboxVectorLayer from 'ol/layer/MapboxVector';

new MapboxVectorLayer({
  styleUrl:
    'https://api.maptiler.com/maps/bright/style.json',
});
    

Decluttered labels
and symbols


import VectorTileLayer from 'ol/layer/VectorTile';
import VectorLayer from 'ol/layer/Vector';

const vectorTile = new VectorTileLayer({
  declutter: true
});

const vector = new VectorLayer({
  declutter: true
});
    

Labels along lines


import {Style, Text} from 'ol/style';

layer.setStyle(feature => {
  return new Style({
    text: new Text({
      placement: 'line',
      text: feature.get('name'),
    }),
  });
});
    

Mapbox Style
(not only vector tiles 😲)


import olms 'ol-mapbox-style';

olms('map', 'https://api.maptiler.com/maps/bright/style.json');
    

OGC API – Tiles ⚗️
(raster)


import OGCMapTile from 'ol/source/OGCMapTile';
import TileLayer from 'ol/layer/Tile';

const layer = new TileLayer({
  source: new OGCMapTile({
    url: 'https://example.com/bluemarble/mercator'
  })
});
    

OGC API – Tiles ⚗️
(vector)


import MVT from 'ol/format/MVT';
import OGCVectorTile from 'ol/source/OGCVectorTile';
import VectorTileLayer from 'ol/layer/VectorTile';

const layer = new VectorTileLayer({
  source: new OGCVectorTile({
    url: 'https://example.com/countries/mercator',
    format: new MVT(),
  })
});
    

WebGL Points 🚀


import WebGLPointsLayer from 'ol/layer/WebGLPoints';

new WebGLPointsLayer({
  source: vectorSource,
  style: {
    symbol: {
      symbolType: 'circle',
      color: 'red',
      size: 12,
      opacity: 1
    }
  }
});
    

WebGL Points
(attribute math)


const size = ['^', ['get', 'mass'], 0.2];
const minYear = 1850;
const maxYear = 2015;
const delta = ['-', maxYear, ['get', 'year']];
const opacity = ['/', delta, maxYear - minYear];
    

WebGL Points
(variables and filters)


const periodEnd = ['var', 'currentYear'];
const periodStart = ['-', periodEnd, 10];
const style = {
  variables: {currentYear: 1950},
  filter: [
    'between', ['get', 'year'], periodStart, periodEnd
  ],
  // ...
};
    

WebGL Tiles
(band math)


const red = ['band', 3];
const nir = ['band', 4];
const diff = ['-', nir, red];
const sum = ['+', nir, red];

const ndvi = ['/', diff, sum];
    

WebGL Tiles
(style expressions)


const layer = new TileLayer({
  source: new GeoTIFF(options),
  style: {
    color: [
      'interpolate', ['linear'], ndvi,
      -1, 'rgb(100, 100, 100)',
      1, 'rgb(0, 69, 0)'
    ],
  }
})
    

WebGL Tiles
(variables)


const style = {
  variables: {
    seaLevel: 0,
  },
  color: [
    'case',
    ['<=', elevation, ['var', 'seaLevel']],
    [139, 212, 255, 1],
    [139, 212, 255, 0],
  ],
}
    

WebGL Tiles
(variables)


slider.addEventListener('input', () => {
  layer.updateStyleVariables({
    seaLevel: parseFloat(slider.value)
  });
});
    

DX

OpenLayers is JSDoc typed
We publish type definitions
You get type checking, autocomplete and hints! 🤩

thanks

Consider becoming a sponsor

project:
https://github.com/sponsors/openlayers

developers: