Filter by reachability
Finding out your vacation rental is too far from the beach is a letdown - symbolize and filter houses (4,389!) based on walk time to the beach in Lerici, Italy
<!DOCTYPE html>
<html>

<head>
    <!--  Include targomo core -->
    <script src="https://releases.targomo.com/core/latest.min.js"></script>
    <!--  Include mapboxgl javascript and css -->
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.52.0/mapbox-gl.js"></script>
    <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.52.0/mapbox-gl.css" rel="stylesheet">
    <style>
        body,
        html {
            margin: 0;
            width: 100%;
            height: 100%;
        }

        #map {
            width: 100%;
            height: 100%;
        }

        #filter {
            position: absolute;
            margin: 10px;
            font-family: 'Open Sans', sans-serif;
            top: 0;
            display: flex;
            align-items: center;
            padding: 5px 8px;
            background: #fff;
        }
    </style>
</head>

<body>
    <!--  where the map will live  -->
    <div id="map"></div>
    <div id="filter">
        <div>Walk time (m)</div>
        <input type="range" min="0" max="30" value="30" name="time" step="1"
            onchange="rangevalue.value=value; filterPoints(value)" />
        <output id="rangevalue">30</output>
    </div>
    <script>
        // create targomo client
        const client = new tgm.TargomoClient('westcentraleurope', '__targomo_key_here__');
        // define map center and search source
        const lnglat = [9.918, 44.08];
        const travelTimes = [300, 600, 900, 1200, 1500, 1800];

        const attributionText = `<a href='https://targomo.com/developers/resources/attribution/' target='_blank'>&copy; Targomo</a>`

        // add the map and set the center
        const map = new mapboxgl.Map({
            container: 'map',
            style: client.basemaps.getGLStyleURL('Gray'),
            zoom: 12.5,
            center: lnglat,
            attributionControl: false,
        })
            .addControl(new mapboxgl.NavigationControl())
            .addControl(new mapboxgl.AttributionControl({ compact: true, customAttribution: attributionText }));

        // disable scroll zoom
        map.scrollZoom.disable();

        async function init() {
            const beachurl = 'https://raw.githubusercontent.com/targomo/data-exports/master/overpass/beach_public_lerici.geojson';
            const houseurl = 'https://raw.githubusercontent.com/targomo/data-exports/master/overpass/building_house_lerici.geojson';
            // get OSM public beaches dataset
            const beaches = await fetch(beachurl).then(async (data) => {
                return JSON.parse(await data.text());
            })

            // get OSM building=house dataset
            const houses = await fetch(houseurl).then(async (data) => {
                return JSON.parse(await data.text());
            })

            map.on('load', () => {
                map.addLayer({
                    "id": "beaches",
                    "type": "circle",
                    "source": {
                        "type": "geojson",
                        "data": beaches
                    },
                    'paint': {
                        'circle-radius': 7,
                        'circle-color': '#DAA520',
                        'circle-stroke-width': 1.5,
                        'circle-stroke-color': '#fff'
                    }
                });

                // create formatted 'sources' for analysis
                const sources = beaches.features.map((beach) => {
                    return {
                        id: beach.properties['@id'],
                        lat: beach.geometry.coordinates[1],
                        lng: beach.geometry.coordinates[0]
                    }
                });

                // create formatted 'targets' for analysis
                const targets = houses.features.map((house) => {
                    return {
                        id: house.properties['@id'],
                        lat: house.geometry.coordinates[1],
                        lng: house.geometry.coordinates[0]
                    }
                });

                // you need to define some options for the reachability service
                const options = {
                    travelType: 'walk',
                    maxEdgeWeight: 30 * 60,
                    edgeWeight: 'time'
                };

                // calculate reachability of banks
                client.reachability.locations(sources, targets, options).then((reachability) => {
                    // assign reachablility to original GeoJSON
                    houses.features.forEach((house) => {
                        const match = reachability.find((location) => {
                            return location.id === house.properties['@id']
                        });
                        house.properties.travelTime = match ? match.travelTime : 30 * 60 + 1;
                    });

                    // add reachable houses, with time symbolized by color
                    map.addLayer({
                        'id': 'houses-reachable',
                        'type': 'circle',
                        'source': {
                            'type': 'geojson',
                            'data': houses
                        },
                        'filter': ['<', 'travelTime', 30 * 60],
                        'paint': {
                            'circle-radius': {
                                'base': 1.75,
                                'stops': [[12, 2], [22, 180]]
                            },
                            'circle-color': {
                                'property': 'travelTime',
                                'stops': [
                                    [360, '#1a9641'],
                                    [720, '#a6d96a'],
                                    [1080, '#ffffbf'],
                                    [1440, '#fdae61'],
                                    [1800, '#d7191c']
                                ]
                            },
                        }
                    }, 'beaches');

                    // add unreachable houses to the map, symbolized gray
                    map.addLayer({
                        'id': 'houses-unreachable',
                        'type': 'circle',
                        'source': {
                            'type': 'geojson',
                            'data': houses
                        },
                        'filter': ['>=', 'travelTime', 30 * 60],
                        'paint': {
                            'circle-radius': {
                                'base': 1.75,
                                'stops': [[12, 2], [22, 180]]
                            },
                            'circle-color': '#666'
                        }
                    }, 'houses-reachable');

                })
            });
        }

        async function filterPoints(minutes) {
            // update the map filter to update symbolization based on range value
            map.setFilter('houses-reachable', ['<', 'travelTime', minutes * 60]);
            map.setFilter('houses-unreachable', ['>=', 'travelTime', minutes * 60 + 1]);
        }

        init()
    </script>
</body>

</html>
content_copy
Copied to clipboard