react-ol v1.3.0

Layers API

API reference for MapTileLayer and MapVectorLayer components

Layers

Layers are the building blocks of your map. They determine what gets rendered and in what order.

MapTileLayer

The MapTileLayer component renders raster tile layers like base maps, satellite imagery, or custom tile servers.

Import

import { MapTileLayer } from '@mixelburg/react-ol';

Props

source (required)

  • Type: TileSource (from OpenLayers)
  • Description: The tile source to render
import { OSM, XYZ } from 'ol/source';

// OpenStreetMap
<MapTileLayer source={new OSM()} />

// Custom tile server
<MapTileLayer
  source={new XYZ({
    url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'
  })}
/>

zIndex

  • Type: number
  • Optional
  • Description: Stacking order of the layer (higher values appear on top)
<MapTileLayer source={new OSM()} zIndex={0} />

opacity

  • Type: number (0-1)
  • Optional
  • Description: Layer opacity level
<MapTileLayer source={new OSM()} opacity={0.5} />

visible

  • Type: boolean
  • Default: true
  • Description: Whether the layer is visible
const [showSatellite, setShowSatellite] = useState(true);
<MapTileLayer source={satelliteSource} visible={showSatellite} />

Examples

Basic Base Map

import { OSM } from 'ol/source';

<OpenLayersMap>
  <MapTileLayer source={new OSM()} />
</OpenLayersMap>

Multiple Tile Layers

import { OSM, XYZ } from 'ol/source';

<OpenLayersMap>
  {/* Base layer */}
  <MapTileLayer source={new OSM()} zIndex={0} />

  {/* Overlay layer */}
  <MapTileLayer
    source={new XYZ({ url: 'https://...' })}
    zIndex={1}
    opacity={0.5}
  />
</OpenLayersMap>

MapVectorLayer

The MapVectorLayer component renders vector features like points, lines, and polygons.

Import

import { MapVectorLayer } from '@mixelburg/react-ol';

Props

layerId (required)

  • Type: string
  • Description: Unique identifier for the layer
<MapVectorLayer layerId="markers">
  {/* features */}
</MapVectorLayer>

style

  • Type: StyleLike (OpenLayers style)
  • Optional
  • Description: Default style for all features in this layer (can be overridden per feature)
import { Circle, Fill, Style } from 'ol/style';

const layerStyle = new Style({
  image: new Circle({
    radius: 6,
    fill: new Fill({ color: 'blue' })
  })
});

<MapVectorLayer layerId="points" style={layerStyle}>
  {/* All points will use this style by default */}
</MapVectorLayer>

features

  • Type: Feature[] (OpenLayers features)
  • Optional
  • Description: Array of OpenLayers features to display (alternative to using feature components as children)
import { Feature } from 'ol';
import { Point } from 'ol/geom';

const features = [
  new Feature({ geometry: new Point([...]) }),
  // more features...
];

<MapVectorLayer layerId="bulk" features={features} />

zIndex

  • Type: number
  • Optional
  • Description: Stacking order of the layer
<MapVectorLayer layerId="background" zIndex={1} />
<MapVectorLayer layerId="foreground" zIndex={2} />

visible

  • Type: boolean
  • Default: true
  • Description: Whether the layer is visible
const [showMarkers, setShowMarkers] = useState(true);
<MapVectorLayer layerId="markers" visible={showMarkers}>
  {/* features */}
</MapVectorLayer>

clustering

  • Type: { enabled: boolean; distance?: number; minDistance?: number }
  • Optional
  • Description: Enable feature clustering for improved performance with many overlapping features
// Enable clustering with default distance (20px)
<MapVectorLayer
  layerId="markers"
  clustering={{ enabled: true }}
>
  {/* features */}
</MapVectorLayer>

// Custom cluster distance (pixels)
<MapVectorLayer
  layerId="markers"
  clustering={{
    enabled: true,
    distance: 40,        // Max distance in pixels for clustering
    minDistance: 10      // Min distance to separate clusters
  }}
>
  {/* features */}
</MapVectorLayer>

Clustering Properties:

  • enabled - Whether clustering is active
  • distance - Maximum pixel distance between features to cluster them together (default: 20)
  • minDistance - Minimum pixel distance between clusters (optional)

When clustering is enabled, the style function receives cluster features with a features property containing the grouped features:

<MapVectorLayer
  layerId="clusters"
  clustering={{ enabled: true, distance: 40 }}
  style={(feature) => {
    const features = feature.get('features');
    const size = features?.length || 1;

    if (size === 1) {
      // Style for individual feature
      return new Style({
        image: new Circle({
          radius: 6,
          fill: new Fill({ color: 'blue' })
        })
      });
    }

    // Style for cluster
    return new Style({
      image: new Circle({
        radius: 10 + Math.min(size / 10, 10),
        fill: new Fill({ color: 'red' })
      }),
      text: new Text({
        text: size.toString(),
        fill: new Fill({ color: 'white' })
      })
    });
  }}
>
  {points.map(point => (
    <PointFeature key={point.id} coordinates={point.coords} />
  ))}
</MapVectorLayer>

children

  • Type: ReactNode
  • Optional
  • Description: Feature components to render in this layer
<MapVectorLayer layerId="my-features">
  <PointFeature coordinates={{ lat: 32, long: 34 }} />
  <LineStringFeature coordinates={[...]} />
  <PolygonFeature coordinates={[...]} />
</MapVectorLayer>

Examples

Basic Vector Layer

<MapVectorLayer layerId="markers">
  <PointFeature
    coordinates={{ lat: 32.0853, long: 34.7818 }}
    style={new Style({
      image: new Circle({
        radius: 8,
        fill: new Fill({ color: 'red' })
      })
    })}
  />
</MapVectorLayer>

Layer with Default Style

import { Circle, Fill, Style } from 'ol/style';

const markerStyle = new Style({
  image: new Circle({
    radius: 6,
    fill: new Fill({ color: 'blue' })
  })
});

<MapVectorLayer layerId="markers" style={markerStyle}>
  {/* All features inherit the style */}
  <PointFeature coordinates={{ lat: 32, long: 34 }} />
  <PointFeature coordinates={{ lat: 32.1, long: 34.1 }} />

  {/* This one overrides the default */}
  <PointFeature
    coordinates={{ lat: 32.2, long: 34.2 }}
    style={new Style({
      image: new Circle({
        radius: 10,
        fill: new Fill({ color: 'red' })
      })
    })}
  />
</MapVectorLayer>

MapWebGLTileLayer

The MapWebGLTileLayer component renders WebGL-accelerated tile layers for improved performance and advanced rendering capabilities. WebGL tile layers are particularly useful for custom styling, data visualization, and working with large datasets.

Import

import { MapWebGLTileLayer } from '@mixelburg/react-ol';

Props

source (required)

  • Type: WebGLTileLayerOptions['source'] (from OpenLayers)
  • Description: The tile source to render with WebGL acceleration
import DataTileSource from 'ol/source/DataTile';

const source = new DataTileSource({
  loader: async (z, x, y) => {
    const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = url;
    await img.decode();
    return img;
  },
});

<MapWebGLTileLayer source={source} />

zIndex

  • Type: number
  • Optional
  • Description: Stacking order of the layer (higher values appear on top)
<MapWebGLTileLayer source={source} zIndex={0} />

opacity

  • Type: number (0-1)
  • Optional
  • Description: Layer opacity level
<MapWebGLTileLayer source={source} opacity={0.8} />

visible

  • Type: boolean
  • Default: true
  • Description: Whether the layer is visible
<MapWebGLTileLayer source={source} visible={true} />

style

  • Type: WebGLTileLayerOptions["style"]
  • Optional
  • Description: WebGL-specific styling configuration for advanced rendering effects
<MapWebGLTileLayer
  source={source}
  style={{
    // WebGL style configuration
  }}
/>

Examples

Basic WebGL Tile Layer

import DataTileSource from 'ol/source/DataTile';

const source = new DataTileSource({
  loader: async (z, x, y) => {
    const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = url;
    await img.decode();
    return img;
  },
});

<OpenLayersMap>
  <MapWebGLTileLayer source={source} />
</OpenLayersMap>

With Custom Opacity

<OpenLayersMap>
  <MapWebGLTileLayer source={source} opacity={0.7} zIndex={0} />
</OpenLayersMap>

MapWebGLVectorLayer

The MapWebGLVectorLayer component renders vector features using WebGL for high-performance rendering. This is ideal for displaying large numbers of features with smooth interactions and animations.

Import

import { MapWebGLVectorLayer } from '@mixelburg/react-ol';

Props

layerId (required)

  • Type: string
  • Description: Unique identifier for the layer
<MapWebGLVectorLayer layerId="webgl-features">
  {/* features */}
</MapWebGLVectorLayer>

style (required)

  • Type: WebGLVectorLayerOptions["style"]
  • Description: WebGL style configuration using expression syntax for high-performance styling
const webglStyle = {
  'circle-radius': 8,
  'circle-fill-color': 'rgba(255, 0, 0, 0.8)',
  'circle-stroke-color': 'rgba(200, 0, 0, 1)',
  'circle-stroke-width': 2,
  'stroke-color': 'rgba(0, 200, 0, 0.9)',
  'stroke-width': 4,
  'fill-color': 'rgba(255, 165, 0, 0.3)',
};

<MapWebGLVectorLayer layerId="features" style={webglStyle}>
  {/* features */}
</MapWebGLVectorLayer>

features

  • Type: Feature[] (OpenLayers features)
  • Optional
  • Description: Array of OpenLayers features to display (alternative to using feature components as children)
import { Feature } from 'ol';
import { Point } from 'ol/geom';

const features = [
  new Feature({ geometry: new Point([...]) }),
  // more features...
];

<MapWebGLVectorLayer layerId="bulk" style={webglStyle} features={features} />

zIndex

  • Type: number
  • Optional
  • Description: Stacking order of the layer
<MapWebGLVectorLayer layerId="background" style={webglStyle} zIndex={1} />

visible

  • Type: boolean
  • Default: true
  • Description: Whether the layer is visible
<MapWebGLVectorLayer layerId="markers" style={webglStyle} visible={true}>
  {/* features */}
</MapWebGLVectorLayer>

disableHitDetection

  • Type: boolean
  • Default: false
  • Description: Disable hit detection for better performance when feature interaction is not needed
<MapWebGLVectorLayer
  layerId="background"
  style={webglStyle}
  disableHitDetection={true}
>
  {/* features */}
</MapWebGLVectorLayer>

children

  • Type: ReactNode
  • Optional
  • Description: Feature components to render in this layer
<MapWebGLVectorLayer layerId="my-features" style={webglStyle}>
  <PointFeature coordinates={{ lat: 32, long: 34 }} />
  <LineStringFeature coordinates={[...]} />
  <PolygonFeature coordinates={[...]} />
  <CircleFeature center={{ lat: 32, long: 34 }} radius={500} />
</MapWebGLVectorLayer>

Examples

Basic WebGL Vector Layer with Different Feature Types

import type { Options as WebGLVectorLayerOptions } from 'ol/layer/WebGLVector';

const vectorLayerStyle: WebGLVectorLayerOptions['style'] = {
  'circle-radius': [
    'case',
    ['==', ['geometry-type'], 'Point'],
    8,
    ['==', ['geometry-type'], 'Circle'],
    ['get', 'radius'],
    0,
  ],
  'circle-fill-color': [
    'case',
    ['==', ['geometry-type'], 'Point'],
    'rgba(255, 0, 0, 0.8)',
    ['==', ['geometry-type'], 'Circle'],
    'rgba(0, 150, 255, 0.3)',
    'transparent',
  ],
  'circle-stroke-color': [
    'case',
    ['==', ['geometry-type'], 'Point'],
    'rgba(200, 0, 0, 1)',
    ['==', ['geometry-type'], 'Circle'],
    'rgba(0, 100, 200, 0.8)',
    'transparent',
  ],
  'circle-stroke-width': 2,
  'stroke-color': [
    'case',
    ['==', ['geometry-type'], 'LineString'],
    'rgba(0, 200, 0, 0.9)',
    ['==', ['geometry-type'], 'Polygon'],
    'rgba(255, 165, 0, 0.9)',
    'rgba(100, 100, 100, 0.8)',
  ],
  'stroke-width': [
    'case',
    ['==', ['geometry-type'], 'LineString'],
    4,
    ['==', ['geometry-type'], 'Polygon'],
    3,
    2,
  ],
  'fill-color': [
    'case',
    ['==', ['geometry-type'], 'Polygon'],
    'rgba(255, 165, 0, 0.3)',
    'transparent',
  ],
};

<OpenLayersMap>
  <MapWebGLTileLayer source={tileSource} />

  <MapWebGLVectorLayer layerId="webgl-features" style={vectorLayerStyle}>
    <PointFeature
      coordinates={{ long: 34.78, lat: 32.085 }}
      onClick={(feature, event) => {
        console.log('Point clicked:', feature, event);
      }}
    />

    <CircleFeature
      center={{ long: 34.79, lat: 32.087 }}
      radius={500}
      onClick={(feature, event) => {
        console.log('Circle clicked:', feature, event);
      }}
    />

    <LineStringFeature
      coordinates={[
        { long: 34.78, lat: 32.085 },
        { long: 34.785, lat: 32.09 },
        { long: 34.79, lat: 32.087 },
      ]}
      onClick={(feature, event) => {
        console.log('Line clicked:', feature, event);
      }}
    />

    <PolygonFeature
      coordinates={[
        { long: 34.775, lat: 32.083 },
        { long: 34.788, lat: 32.083 },
        { long: 34.788, lat: 32.092 },
        { long: 34.775, lat: 32.092 },
      ]}
      onClick={(feature, event) => {
        console.log('Polygon clicked:', feature, event);
      }}
    />
  </MapWebGLVectorLayer>
</OpenLayersMap>

High-Performance Layer with Disabled Hit Detection

// For static features where you don't need click/hover events
<MapWebGLVectorLayer
  layerId="static-background"
  style={webglStyle}
  disableHitDetection={true}
>
  {/* Thousands of features */}
</MapWebGLVectorLayer>

WebGL Style Expressions

WebGL vector layer styles use expression-based syntax for powerful, data-driven styling:

const style = {
  // Simple static values
  'circle-radius': 10,
  'circle-fill-color': 'red',

  // Conditional styling
  'circle-radius': [
    'case',
    ['==', ['geometry-type'], 'Point'],
    8,
    ['get', 'radius'],  // Use feature property
  ],

  // Data-driven colors
  'circle-fill-color': [
    'interpolate',
    ['linear'],
    ['get', 'value'],
    0, 'blue',
    50, 'yellow',
    100, 'red',
  ],
};

Performance Comparison

When to Use WebGL Layers

Use MapWebGLTileLayer and MapWebGLVectorLayer when:

  • Rendering large numbers of features (1000+)
  • Need advanced styling with expressions
  • Require smooth animations and interactions
  • Working with data visualizations
  • Performance is critical

Use standard MapTileLayer and MapVectorLayer when:

  • Simple maps with few features
  • Standard styling is sufficient
  • Broader browser compatibility is needed
  • Easier debugging and development
```tsx
function MyMap() {
  const [showMarkers, setShowMarkers] = useState(true);
  const [showPolygons, setShowPolygons] = useState(true);

  return (
    <div>
      <button onClick={() => setShowMarkers(!showMarkers)}>
        Toggle Markers
      </button>
      <button onClick={() => setShowPolygons(!showPolygons)}>
        Toggle Polygons
      </button>

      <OpenLayersMap>
        <MapTileLayer source={new OSM()} />

        <MapVectorLayer layerId="markers" visible={showMarkers}>
          <PointFeature coordinates={{ lat: 32, long: 34 }} />
        </MapVectorLayer>

        <MapVectorLayer layerId="polygons" visible={showPolygons}>
          <PolygonFeature coordinates={[...]} />
        </MapVectorLayer>
      </OpenLayersMap>
    </div>
  );
}
```

#### Organizing Complex Maps

```tsx
<OpenLayersMap>
  {/* Base layer at the bottom */}
  <MapTileLayer source={new OSM()} zIndex={0} />

  {/* Background features */}
  <MapVectorLayer layerId="zones" zIndex={1}>
    <PolygonFeature coordinates={zoneCoords} />
  </MapVectorLayer>

  {/* Roads/paths */}
  <MapVectorLayer layerId="roads" zIndex={2}>
    <LineStringFeature coordinates={roadCoords} />
  </MapVectorLayer>

  {/* Points of interest on top */}
  <MapVectorLayer layerId="pois" zIndex={3}>
    <PointFeature coordinates={poi1} />
    <PointFeature coordinates={poi2} />
  </MapVectorLayer>
</OpenLayersMap>
```

## Layer Ordering

Layers are rendered in order based on their `zIndex` prop:

- **Lower zIndex** = rendered first (bottom)
- **Higher zIndex** = rendered last (top)
- **No zIndex** = rendered in DOM order

```tsx
<MapTileLayer source={new OSM()} zIndex={0} />        {/* Bottom */}
<MapVectorLayer layerId="areas" zIndex={1} />         {/* Middle */}
<MapVectorLayer layerId="markers" zIndex={2} />       {/* Top */}
```

## Performance Tips

1. **Limit feature count**: For many features, consider clustering or pagination
2. **Use appropriate zoom levels**: Hide detailed features at low zoom
3. **Optimize styles**: Reuse style instances instead of creating new ones
4. **Layer visibility**: Hide layers when not needed instead of unmounting

```tsx
// ✅ Good: Reuse style
const markerStyle = new Style({ ... });
<MapVectorLayer style={markerStyle} />

// ❌ Less optimal: Create new style on each render
<MapVectorLayer style={new Style({ ... })} />
```

On this page