Add a custom style layer

Use a custom style layer to render custom WebGL content.

NPM module setup


npm install --save @maptiler/sdk
import { Map, MapStyle, config, MercatorCoordinate } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';

config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = (window.map = new Map({
    container: 'map',
    zoom: 3,
    center: [7.5, 58],
    style: MapStyle.STREETS,
    canvasContextAttributes: {antialias: true}  // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));

// create a custom style layer to implement the WebGL content
const highlightLayer = {
    id: 'highlight',
    type: 'custom',

    // method called when the layer is added to the map
    // Search for StyleImageInterface in https://maplibre.org/maplibre-gl-js/docs/API/
    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
        this.program = gl.createProgram();
        gl.attachShader(this.program, vertexShader);
        gl.attachShader(this.program, fragmentShader);
        gl.linkProgram(this.program);

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

        // define vertices of the triangle to be rendered in the custom style layer
        const helsinki = MercatorCoordinate.fromLngLat({
            lng: 25.004,
            lat: 60.239
        });
        const berlin = MercatorCoordinate.fromLngLat({
            lng: 13.403,
            lat: 52.562
        });
        const kyiv = MercatorCoordinate.fromLngLat({
            lng: 30.498,
            lat: 50.541
        });

        // create and initialize a WebGLBuffer to store vertex and color data
        this.buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
        gl.bufferData(
            gl.ARRAY_BUFFER,
            new Float32Array([
                helsinki.x,
                helsinki.y,
                berlin.x,
                berlin.y,
                kyiv.x,
                kyiv.y
            ]),
            gl.STATIC_DRAW
        );
    },

    // method fired on each animation frame
    render (gl, args) {
        gl.useProgram(this.program);
        gl.uniformMatrix4fv(
            gl.getUniformLocation(this.program, 'u_matrix'),
            false,
            args.defaultProjectionData.mainMatrix
        );
        gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
        gl.enableVertexAttribArray(this.aPos);
        gl.vertexAttribPointer(this.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, 'Building');
});
Add an animated icon to the map

Add an animated icon to the map

Examples

Add animated icons generated at runtime using Canvas API.

Add a canvas source

Add a canvas source

Examples

Integrate a dynamic HTML canvas source into the map.

Add a generated icon to the map

Add a generated icon to the map

Examples

Add custom map icons generated dynamically at runtime.

Generate and add a missing icon to the map

Generate a missing icon to the map

Examples

Dynamically generate and add missing icons to the map.

Was this helpful?