Skip to content

Animate a Timeline

Display data over a particular time period using a time slider.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset='utf-8'>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://cdn.smartmaps.cloud/packages/smartmaps/smartmaps-gl/v2/umd/smartmaps-gl.min.js"></script>
        <style>
            body { 
                margin: 0; 
                padding: 0; 
                }

            html, 
            body, 
            #map { 
                height: 100%; 
                }
        </style>
    </head>

    <body>
    <style>
        .map-overlay {
            font: 12px/20px Arial, Helvetica, sans-serif;
            position: absolute;
            width: 25%;
            top: 0;
            left: 0;
            padding: 10px;
        }

        .map-overlay .map-overlay-inner {
            background-color: #fff;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            border-radius: 3px;
            padding: 10px;
            margin-bottom: 10px;
        }

        .map-overlay h2 {
            line-height: 24px;
            display: block;
            margin: 0 0 10px;
        }

        .map-overlay .legend .bar {
            height: 10px;
            width: 100%;
            background: linear-gradient(to right, #fca107, #7f3121);
        }

        .map-overlay input {
            background-color: transparent;
            display: inline-block;
            width: 100%;
            position: relative;
            margin: 0;
            cursor: ew-resize;
        }
    </style>

    <div id="map"></div>

    <div class="map-overlay top">
        <div class="map-overlay-inner">
            <h2>Significant earthquakes in 2015</h2>
            <label id="month" for="slider"></label>
            <input id="slider" type="range" min="0" max="11" step="1" value="0" />
        </div>
        <div class="map-overlay-inner">
            <div id="legend" class="legend">
                <div class="bar"></div>
                <div>Magnitude (m)</div>
            </div>
        </div>
    </div>

    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script>
        const map = new smartmapsgl.Map({
            apiKey: "INSERT API-KEY",
                container: "map",
                center: { lat: 29.02164948779226, lng: 8.439330018049352 },
                zoom: 1,
                style: smartmapsgl.MapStyle.LIGHT
        });

        const months = [
            'January',
            'February',
            'March',
            'April',
            'May',
            'June',
            'July',
            'August',
            'September',
            'October',
            'November',
            'December'
        ];

        function filterBy(month) {
            const filters = ['==', 'month', month];
            map.setFilter('earthquake-circles', filters);
            map.setFilter('earthquake-labels', filters);

            // Set the label to the month
            document.getElementById('month').textContent = months[month];
        }


        map.on('load', () => {
            // Data courtesy: https://www.usgs.gov/programs/earthquake-hazards

            // Here we're using d3 to help us make the ajax request but you can use
            // Any request method (library or otherwise) you wish.
            d3.json(
                '../data/earthquakes2015.geojson',
                (err, data) => {
                    if (err) throw err;

                    //Create a month property value based on time used to filter against.
                    data.features = data.features.map((d) => {
                        d.properties.month = new Date(d.properties.time).getMonth();
                        return d;                   
                    });

                    map.addSource('earthquakes', {
                        'type': 'geojson',
                        data
                    });

                    map.addLayer({
                        'id': 'earthquake-circles',
                        'type': 'circle',
                        'source': 'earthquakes',
                        'filter': ['has', 'mag'],
                        'paint': {
                            'circle-color': [
                                'interpolate',
                                ['linear'],
                                ['get', 'mag'],
                                6,
                                '#FCA107',
                                8,
                                '#7F3121'
                            ],
                            'circle-opacity': 0.75,
                            'circle-radius': [
                                'interpolate',
                                ['linear'],
                                ['get', 'mag'],
                                6,
                                20,
                                8,
                                40
                            ]
                        }
                    });

                    map.addLayer({
                        'id': 'earthquake-labels',
                        'type': 'symbol',
                        'source': 'earthquakes',
                        'filter': ['has', 'mag'],
                        'layout': {
                            'text-field': [
                                'concat',
                                ['to-string', ['get', 'mag']],
                                'm'
                            ],
                            'text-font': [
                                'Inter-Bold'
                            ],
                            'text-size': 12
                        },
                        'paint': {
                            'text-color': 'rgba(0,0,0,0.5)'
                        }
                    });

                    // Set filter to first month of the year, 0 = January
                    filterBy(0);

                    document
                        .getElementById('slider')
                        .addEventListener('input', (e) => {
                            const month = parseInt(e.target.value, 10);
                            filterBy(month);
                        });
                }
            );
        });
    </script>
    </body>
</html>