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>