Custom earthquake symbols using a shader

Custom earthquake symbols using a shader

This example customizes the symbols displayed by the earthquakes layer using a custom fragment shader.

Custom shaders can be used for symbol or circle layer types to create a unique animated visual effect for each symbol based on the feature's data and properties.

custom-earthquake-shader.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>MapsGL SDK - Custom earthquake symbols using a shader</title>
    <meta name="description" content="Use a custom WebGL fragment shader to apply unique and animated visual effects to earthquake data." />
    <meta name="viewport" content="width=device-width, initial-scale=1">
 
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.8.0/mapbox-gl.css" rel="stylesheet" />
    <script defer src="https://api.mapbox.com/mapbox-gl-js/v2.8.0/mapbox-gl.js"></script>
 
    <link href="https://cdn.aerisapi.com/sdk/js/mapsgl/latest/aerisweather.mapsgl.css" rel="stylesheet" />
    <script defer src="https://cdn.aerisapi.com/sdk/js/mapsgl/latest/aerisweather.mapsgl.js"></script>
    
 
    <style>
    body, html {
        margin: 0;
        padding: 0;
    }
    #map {
        height: 100vh;
        width: 100%;
    }
    </style>
 
</head>
<body>
    <div id="map"></div>
 
    <script>
    window.addEventListener('load', () => {
 
        mapboxgl.accessToken = 'MAPBOX_TOKEN';
        const map = new mapboxgl.Map({
            container: document.getElementById('map'),
            style: 'mapbox://styles/mapbox/light-v9',
            center: [124.091, 26.232],
            zoom: 2
        });
        
        const account = new aerisweather.mapsgl.Account('CLIENT_ID', 'CLIENT_SECRET');
        const controller = new aerisweather.mapsgl.MapboxMapController(map, { account });
 
        controller.on('load', () => {
            controller.addWeatherLayer('earthquakes', {
                type: 'symbol',
                source: 'earthquakes',
                paint: {
                    symbol: {
                        shader: `
            // https://www.shadertoy.com/view/ldycR3
            #extension GL_OES_standard_derivatives : enable
 
            precision mediump float;
 
            uniform vec2 resolution;
            uniform float dpr;
            uniform float time;
 
            varying vec2 vUv;
            varying vec2 vPosition;
            varying float vFactor;
            varying float vRandom;
 
            float saturate(float x) {
            return clamp(x, 0.0, 1.0);
            }
 
            vec3 hsb2rgb(in vec3 c) {
            vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0,
                        0.0,
                        1.0);
            rgb = rgb*rgb*(3.0-2.0*rgb);
            return c.z * mix( vec3(1.0), rgb, c.y);
            }
 
            void main() {
            vec2 pos = vUv;
            float t = time;
 
            float dist = length(2.0 * pos - 1.0) * 2.0;
            vec2 p = vec2(dist);
 
            float r = length(p) * 0.9;
            vec3 color = hsb2rgb(vec3(0.03, 0.7, 0.6));
 
            float a = pow(r, 3.0);
            float b = sin(r * 1.8 - 1.6);
            float c = sin(r - 0.010);
            float s = sin(a - t * 2.0 + b) * c;
 
            color *= abs(1.0 / (s * 1.8)) - 0.01;
 
            float d = length(2.0 * pos - 1.0);
            // float delta = fwidth(d);
            float alpha = 1.0 - d;
            // alpha *= min(1.0, 0.2 + vFactor);
 
            gl_FragColor = vec4(color, alpha);
            gl_FragColor.rgb *= gl_FragColor.a;
            }
                        `,
                        animated: true,
                        pitchWithMap: true,
                        // blending: 2,
                        size: (data) => {
                            const mag = Math.max(data.report?.mag || 1);
                            const size = 20 + 100 * (mag / 10);
                            return { width: size, height: size };
                        }
                    }
                }
            });
        });
 
    });
    </script>
 
</body>
</html>