Colorful line

Open in CodeSandbox

It is usually used to show the traffic jams.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
            import {LOCATION, ROUTE} from '../variables';
            import {PASSED_ROUTE_STYLE, fetchRoute} from './common';
            
            window.map = null;
            
            main();
            
            async function main() {
                // Waiting for all API elements to be loaded
                await mappable.ready;
                const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature} = mappable;
            
                // Initialize the map
                map = new MMap(document.getElementById('app'), {location: LOCATION, showScaleInCopyrights: true}, [
                    new MMapDefaultSchemeLayer({}),
                    new MMapDefaultFeaturesLayer({})
                ]);
            
                // Fetch the route and add it to the map
                const route = await fetchRoute(ROUTE);
                if (route) {
                    const routeFeature = new MMapFeature({
                        geometry: route.geometry, // Assuming route.geometry is of type LineStringGeometry
                        style: PASSED_ROUTE_STYLE
                    });
                    map.addChild(routeFeature);
                }
            }
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
            import type {LineStringGeometry, RouteFeature} from '@mappable-world/mappable-types';
            import {PASSED_ROUTE_STYLE, fetchRoute} from './common';
            import {LOCATION, ROUTE} from '../variables';
            
            window.map = null;
            
            main();
            async function main() {
                // For each object in the JS API, there is a React counterpart
                // To use the React version of the API, include the module @mappable-world/mappable-reactify
                const [mappableReact] = await Promise.all([mappable.import('@mappable-world/mappable-reactify'), mappable.ready]);
                const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
                const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature} = reactify.module(mappable);
            
                const {useState, useEffect} = React;
            
                function App() {
                    const [route, setRoute] = useState<RouteFeature>(null);
            
                    useEffect(() => {
                        fetchRoute(ROUTE).then((route) => setRoute(route));
                    }, []);
            
                    return (
                        // Initialize the map and pass initialization parameters
                        <MMap location={LOCATION} showScaleInCopyrights={true} ref={(x) => (map = x)}>
                            {/* Add a map scheme layer */}
                            <MMapDefaultSchemeLayer />
                            {/* Add a layer of geo objects to display the markers */}
                            <MMapDefaultFeaturesLayer />
            
                            {route && <MMapFeature geometry={route.geometry as LineStringGeometry} style={PASSED_ROUTE_STYLE} />}
                        </MMap>
                    );
                }
            
                ReactDOM.render(
                    <React.StrictMode>
                        <App />
                    </React.StrictMode>,
                    document.getElementById('app')
                );
            }
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets=" typescript" type="text/babel">
            import {LOCATION, ROUTE} from '../variables';
            import {PASSED_ROUTE_STYLE, fetchRoute} from './common';
            
            window.map = null;
            
            async function main() {
                // For each object in the JS API, there is a Vue counterpart
                // To use the Vue version of the API, include the module @mappable-world/mappable-vuefy
                const [mappableVue] = await Promise.all([mappable.import('@mappable-world/mappable-vuefy'), mappable.ready]);
                const vuefy = mappableVue.vuefy.bindTo(Vue);
                const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature} = vuefy.module(mappable);
            
                const app = Vue.createApp({
                    components: {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature},
                    setup() {
                        const refMap = (ref) => {
                            window.map = ref?.entity; // Store the map instance in a global variable
                        };
            
                        const route = Vue.ref(null); // Reactive reference for the route
            
                        // Fetch the route when the component is mounted
                        Vue.onMounted(async () => {
                            const fetchedRoute = await fetchRoute(ROUTE);
                            if (fetchedRoute) {
                                route.value = fetchedRoute; // Set the fetched route
                            }
                        });
            
                        return {LOCATION, refMap, route, PASSED_ROUTE_STYLE};
                    },
                    template: `
                  <MMap :location="LOCATION" :showScaleInCopyrights="true" :ref="refMap">
                    <MMapDefaultSchemeLayer />
                    <MMapDefaultFeaturesLayer />
                    <MMapFeature 
                      v-if="route" 
                      :geometry="route.geometry" 
                      :style="PASSED_ROUTE_STYLE" 
                    />
                  </MMap>`
                });
            
                app.mount('#app');
            }
            
            main();
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
import type {LngLat, MMapLocationRequest} from '@mappable-world/mappable-types';

export const LOCATION: MMapLocationRequest = {
    center: [55.166611, 25.062854], // starting position [lng, lat]
    zoom: 15.3 // starting zoom
};

export const ROUTE: LngLat[] = [
    [55.184226, 25.069446],
    [55.170017, 25.061783],
    [55.162822, 25.067076],
    [55.154957, 25.072835]
];
import {DrawingStyle, LngLat, Palette} from '@mappable-world/mappable-types';

mappable.ready.then(() => {
    // 
});

export async function fetchRoute(points: LngLat[]) {
    // Request a route from the Router API with the specified parameters.
    const routes = await mappable.route({
        points, // Start and end points of the route LngLat[]
        type: 'driving', // Type of the route
        bounds: true // Flag indicating whether to include route boundaries in the response
    });

    // Check if a route was found
    if (!routes[0]) return;

    // Convert the received route to a RouteFeature object.
    const route = routes[0].toRoute();

    // Check if a route has coordinates
    if (route.geometry.coordinates.length == 0) return;

    return route;
}

function hexToRgb(hex) {
    // Convert hex to RGB
    const bigint = parseInt(hex.slice(1), 16);
    const r = (bigint >> 16) & 255;
    const g = (bigint >> 8) & 255;
    const b = bigint & 255;
    return [r, g, b];
}

function rgbToHex(r, g, b) {
    // Convert RGB back to hex
    return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
}

function interpolateColor(color1, color2, factor) {
    const [r1, g1, b1] = hexToRgb(color1);
    const [r2, g2, b2] = hexToRgb(color2);
    const r = Math.round(r1 + (r2 - r1) * factor);
    const g = Math.round(g1 + (g2 - g1) * factor);
    const b = Math.round(b1 + (b2 - b1) * factor);
    return rgbToHex(r, g, b);
}

function generateGradientColors(stops, totalColors) {
    const colors = [];
    const totalStops = stops.length;

    for (let i = 0; i < totalStops - 1; i++) {
        const startColor = stops[i].color;
        const endColor = stops[i + 1].color;
        const startPercent = stops[i].percent;
        const endPercent = stops[i + 1].percent;

        const segmentColors = Math.floor((totalColors * (endPercent - startPercent)) / 100);

        for (let j = 0; j <= segmentColors; j++) {
            const factor = j / segmentColors;
            colors.push(interpolateColor(startColor, endColor, factor));
        }
    }

    return colors;
}

// Define the color stops
const colorStops = [
    {color: '#FF5E5E', percent: 0},
    {color: '#FFD333', percent: 33},
    {color: '#5ED686', percent: 66},
    {color: '#7D90F0', percent: 100}
];

// Generate 400 colors
const gradientColors = generateGradientColors(colorStops, 400);
const palette = gradientColors.map((color) => ({color, count: 1}));

export const PASSED_ROUTE_STYLE: DrawingStyle = {
    simplificationRate: 0,
    stroke: [{palette, width: 10}]
};