Adding Custom Overlays in map

This documentation provides methods for creating a custom canvas overlay on top of a map. This is useful for more dynamic overlays, like drawing on the map or creating custom animations.

Creating a Custom Overlay

To add a custom overlay, you can use the addLayer method with a type 'custom' layer.

Initialization with `onAdd`

The onAdd function is called when the layer is added to the map. Use this to set up any resources your layer will need, like creating a canvas, initializing WebGL, or setting up a 3D scene. This takes two parameters:
  • 'map' : The map instance, providing access to the map's API.
  • 'gl' : The WebGL context, particularly important for 3D rendering.
onAdd: function (map, gl) {
  // Initialize resources, like creating a canvas or setting up 3D objects
}

Rendering with `render`

The render function is where the magic happens. It’s called every time to update the visual content of your custom layer. This takes two parameters:
  • 'gl' : The WebGL context, used if rendering with WebGL.
  • 'matrix' : The transformation matrix representing the map's current state (e.g., zoom, rotation).
In this function, you draw your custom content on the map, be it a simple 2D graphic or a complex 3D scene
render: function (gl, matrix) {
  // Draw or update the custom content
}

Example

let program, aPos, buffer;
  const highlightLayer = {
    id: 'highlight',
    type: 'custom', // keep type as custom
    onAdd(map,gl) {
      // create GLSL source for vertex shader
      const vertexSource = `#version 300 es
        uniform mat4 u_matrix;
        in vec2 a_pos;
        void main() {
          gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
        }`

      // create GLSL source for fragment shader
      const fragmentSource = `#version 300 es
        out highp vec4 fragColor;
        void main() {
          fragColor = vec4(1.0, 0.0, 0.0, 0.5);
        }`

      // create a vertex shader
      const vertexShader = gl.createShader(gl.VERTEX_SHADER)
      gl.shaderSource(vertexShader, vertexSource)
      gl.compileShader(vertexShader)
      // create a fragment shader
      const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
      gl.shaderSource(fragmentShader, fragmentSource)
      gl.compileShader(fragmentShader)

      // link the two shaders into a WebGL program
      program = gl.createProgram()
      gl.attachShader(program, vertexShader)
      gl.attachShader(program, fragmentShader)
      gl.linkProgram(program)

      aPos = gl.getAttribLocation(program, 'a_pos')

      // define vertices of the shape/layer to be rendered in the custom style layer
      const coord1 = olaMaps.getMercatorCoordinate().fromLngLat({
        lng: 76.9629,
        lat: 26.1751,
      })
      const coord2 = olaMaps.getMercatorCoordinate().fromLngLat({
        lng: 78.1751,
        lat: 28.562,
      })
      const coord3 = olaMaps.getMercatorCoordinate().fromLngLat({
        lng: 79.498,
        lat: 27.541,
      })

      // create and initialize a WebGLBuffer to store vertex and color data
      buffer = gl.createBuffer()
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
      gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([coord1.x, coord1.y, coord2.x, coord2.y, coord3.x, coord3.y]),
        gl.STATIC_DRAW,
      )
    },

    // method fired on each animation frame
    render(gl,matrix) {
      gl.useProgram(program)
      gl.uniformMatrix4fv(gl.getUniformLocation(program, 'u_matrix'), false, matrix)
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
      gl.enableVertexAttribArray(aPos)
      gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0)
      gl.enable(gl.BLEND)
      gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3)
    },
  }

  // add the custom style layer to the map
  map.on('load', () => {
    map.addLayer(highlightLayer)
  })