Skip to content

Draw a Gradient Line

Apply a smooth color gradient along a line using the line-gradient paint property and line-progress expression.

Requirements

To use line-gradient, you must set lineMetrics: true on the source:

javascript
map.addSource('route', {
  type: 'geojson',
  lineMetrics: true,   // ← required for line-gradient
  data: {
    type: 'Feature',
    geometry: { type: 'LineString', coordinates: [...] }
  }
});

Gradient Paint Property

javascript
map.addLayer({
  id: 'gradient-line',
  type: 'line',
  source: 'route',
  layout: { 'line-join': 'round', 'line-cap': 'round' },
  paint: {
    'line-width': 6,
    'line-gradient': [
      'interpolate',
      ['linear'],
      ['line-progress'],   // 0 = line start, 1 = line end
      0,   '#ef4444',      // red at start
      0.5, '#eab308',      // yellow at midpoint
      1,   '#22c55e',      // green at end
    ]
  }
});

Common Gradient Themes

javascript
// Speed (slow → fast)
'line-gradient': ['interpolate', ['linear'], ['line-progress'],
  0, '#22c55e',   // green (slow)
  0.5, '#eab308', // yellow (medium)
  1, '#ef4444'    // red (fast)
]

// Elevation (low → high)
'line-gradient': ['interpolate', ['linear'], ['line-progress'],
  0, '#3b82f6',   // blue (sea level)
  0.5, '#84cc16', // lime (mid)
  1, '#7c3aed'    // purple (high)
]

// Progress indicator
'line-gradient': ['interpolate', ['linear'], ['line-progress'],
  0, '#3b82f6',   // start color
  1, '#a855f7'    // end color
]

Complete Example

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>#map { height: 500px; width: 100%; }</style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      const map = new mapmetricsgl.Map({
        container: 'map',
        style: '<StyleFile_URL_with_Token>',
        center: [5, 50],
        zoom: 4
      });

      const route = [
        [-3.7038, 40.4168],
        [2.3499, 48.853],
        [13.405, 52.52],
        [28.9784, 41.0082],
      ];

      map.on('load', () => {
        map.addSource('route', {
          type: 'geojson',
          lineMetrics: true,
          data: { type: 'Feature', geometry: { type: 'LineString', coordinates: route } }
        });

        map.addLayer({
          id: 'gradient',
          type: 'line',
          source: 'route',
          layout: { 'line-join': 'round', 'line-cap': 'round' },
          paint: {
            'line-width': 6,
            'line-gradient': [
              'interpolate', ['linear'], ['line-progress'],
              0, '#ef4444',
              0.5, '#eab308',
              1, '#22c55e'
            ]
          }
        });

        const bounds = route.reduce(
          (b, c) => b.extend(c),
          new mapmetricsgl.LngLatBounds(route[0], route[0])
        );
        map.fitBounds(bounds, { padding: 60 });
      });
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const route = [
  [-3.7038, 40.4168],
  [2.3499, 48.853],
  [13.405, 52.52],
  [28.9784, 41.0082],
];

const GradientLine = () => {
  const mapContainer = useRef(null);
  const map = useRef(null);

  useEffect(() => {
    if (map.current) return;

    map.current = new mapmetricsgl.Map({
      container: mapContainer.current,
      style: '<StyleFile_URL_with_Token>',
      center: [5, 50],
      zoom: 4
    });

    map.current.on('load', () => {
      map.current.addSource('route', {
        type: 'geojson',
        lineMetrics: true,
        data: { type: 'Feature', geometry: { type: 'LineString', coordinates: route } }
      });

      map.current.addLayer({
        id: 'gradient',
        type: 'line',
        source: 'route',
        layout: { 'line-join': 'round', 'line-cap': 'round' },
        paint: {
          'line-width': 6,
          'line-gradient': [
            'interpolate', ['linear'], ['line-progress'],
            0, '#ef4444',
            0.5, '#eab308',
            1, '#22c55e'
          ]
        }
      });

      const bounds = route.reduce(
        (b, c) => b.extend(c),
        new mapmetricsgl.LngLatBounds(route[0], route[0])
      );
      map.current.fitBounds(bounds, { padding: 60 });
    });

    return () => { map.current?.remove(); map.current = null; };
  }, []);

  return <div ref={mapContainer} style={{ height: '500px', width: '100%' }} />;
};

export default GradientLine;

For more information, visit the MapMetrics GitHub repository.