Filter Points of Interest by travel time (Google maps)

In this example we will show you how you can use the TimeService to filter a list of your entities by travel time, starting from a source location. In our case we will use all museums from OpenStreetMaps which have a non-empty name and website.

With this feature users can instantly see which points of interest are closest to them, with respect to the actual travel time and not just beeline. Note that this would not be possible with traditional routing services like Google Maps, since you would have to make one request per place of interest.

Filter Points of Interest by travel time

See which points of interest are closest by bike, with respect to the actual travel time.

GET YOUR FREE API KEY to use this example
hide code
<!DOCTYPE html>
<html>
<head>
  <!--  Include jquery - required for XHR requests -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <!--  Include google maps api -->
  <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&amp;sensor=false&amp;key=your_google_maps_key" type="text/javascript"></script>
  <!--  Include r360.js -->
  <script src="https://releases.route360.net/r360-js/latest.js"></script>
  <!--  Include dragdealer slider bar    -->
  <script src="https://cdn.rawgit.com/skidding/dragdealer/master/src/dragdealer.js"></script>
  <!--   Include font awesome   -->
  <script src="https://use.fontawesome.com/d0a009c133.js"></script>
  <style>
    html, body { width: 100%; height: 100%; margin: 0; font-family: sans-serif; }
    #map { width: 100%; height: 100%; }
    .gm-style-iw p { margin: 5px 0 }
    .controls-panel {
      position: absolute;
      top: 0px;
      left: 0px;
      right: 0px;
      background: rgba(255, 255, 255, 0.8);
      padding: 10px;
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      z-index: 1000;
    }
    .time-value {
      font-size: 16px;
      font-weight: 500;
      margin-right: 10px;
      width: 100px;
      color: rgba(0, 0, 0, .5);
      text-align: right;
    }
    #slider { position: relative; height: 20px; width: 50%; }
    #slider .handle {
      position: absolute;
      top: 0;
      left: 0;
      cursor: pointer;
      width: 20px;
      height: 20px;
      background: #00838f;
      border-radius: 10px;
      z-index: 2;
    }
    #slider:after {
      content: "";
      position: absolute;
      margin-top: 8px;
      height: 4px;
      background: rgba(0, 0, 0, .5);
      border-radius: 2px;
      left: 0;
      right: 0;
      z-index: 1;
    }
  </style>
</head>

<body>
  <!--  where the map will live  -->
  <div id="map"></div>
  <div class="controls-panel">
    <div class="time-value">
      <i class="fa fa-clock-o" aria-hidden="true"></i>
      <span id="actual-time">30</span>min
    </div>
    <div id="slider">
      <div class="handle"></div>
    </div>
  </div>
  
  <script>
      // osm museums with valid url field
    var museumsBB = [{"id":15968753,"name":"Altes Museum","url":"http://www.smb.museum/smb/standorte/index.php?lang=de&p=2&objID=24&n=2&r=1","lon":13.3988098410779,"lat":52.5194482697477},{"id":18578139,"name":"Neues Museum","url":"http://www.neues-museum.de","lon":13.3977318647919,"lat":52.5201792598004},{"id":22990151,"name":"Musikinstrumenten-Museum","url":"http://www.sim.spk-berlin.de/mim_3.html","lon":13.370790858961,"lat":52.510457544161},{"id":22990228,"name":"Kunstgewerbemuseum","url":"http://www.smb.museum/smb/standorte/index.php?lang=de&p=2&objID=37&n=8","lon":13.3673485161884,"lat":52.5097509246173},{"id":22990276,"name":"Kupferstichkabinett","url":"http://www.smb.museum/smb/standorte/index.php?p=2&objID=39","lon":13.3666604757285,"lat":52.5084017983238},{"id":23813200,"name":"Nikolaikirche","url":"http://www.stadtmuseum.de/nikolaikirche","lon":13.4074901704182,"lat":52.5168055278862},{"id":26144213,"name":"Gründerzeitmuseum im Gutshaus Mahlsdorf","url":"http://www.gruenderzeitmuseum.de","lon":13.6139832649212,"lat":52.5024636041934},{"id":26247891,"name":"Museum für Fotografie","url":"http://www.smb.museum/smb/standorte/index.php?lang=de&p=2&objID=6124&n=12","lon":13.3320859102401,"lat":52.508140292441},{"id":27120308,"name":"Museum Neukölln","url":"www.museum-neukoelln.de","lon":13.43776755,"lat":52.44596185},{"id":27182821,"name":"Botanisches Museum Berlin-Dahlem","url":"http://www.bgbm.org/bgbm/museum/","lon":13.3051390048542,"lat":52.4583581560775},{"id":28147152,"name":"Museumsdorf Düppel","url":"http://www.dueppel.de/","lon":13.2334496216724,"lat":52.4251563984244},{"id":29490400,"name":"Museum für Asiatische Kunst","url":"http://www.smb.museum/smb/sammlungen/details.php?objID=12904","lon":13.2922617644695,"lat":52.4559466132299},{"id":31283095,"name":"Haus am Waldsee","url":"http://www.hausamwaldsee.de","lon":13.2384135246861,"lat":52.4420693652737},{"id":31415713,"name":"Schöneberg Museum","url":"http://www.jugendmuseum.de/m_schoeneberg/dashaus_fr.html","lon":13.3509769927722,"lat":52.4839053697533},{"id":32541759,"name":"MACHmit! Museum für Kinder","url":"http://www.machmitmuseum.de","lon":13.4227734046356,"lat":52.5405355583121},{"id":33910270,"name":"Schmetterlingshorst","url":"http://www.schmetterlingshorst.de/","lon":13.6096067600917,"lat":52.4125698609369},{"id":43173495,"name":"Tränenpalast","url":"http://www.traenenpalast.de","lon":13.3870976693499,"lat":52.5208751114516},{"id":44038022,"name":"Villa Schöningen","url":"http://www.villa-schoeningen.de/","lon":13.0876676798627,"lat":52.4136114585373},{"id":47423543,"name":"Science Center Medizintechnik","url":"http://www.sciencecenter-medizintechnik.de","lon":13.3773362288055,"lat":52.5112752151801},{"id":48472661,"name":"Käthe-Kollwitz-Museum Berlin","url":"http://www.kaethe-kollwitz.de/","lon":13.3269243807532,"lat":52.5016866584425},{"id":49055962,"name":"Jagdschloss Grunewald","url":"http://www.spsg.de/index.php?id=140","lon":13.2616549407188,"lat":52.4670861383712},{"id":49055979,"name":"Brücke Museum","url":"http://www.bruecke-museum.de/","lon":13.2746692520118,"lat":52.4668808606349},{"id":49900345,"name":"Blindenmuseum","url":"http://www.blindenmuseum-berlin.de","lon":13.3150827580171,"lat":52.455801544996},{"id":79611278,"name":"Museum Charlottenburg-Wilmersdorf in der Villa Oppenheim","url":"http://www.villa-oppenheim-berlin.de/","lon":13.2980018314897,"lat":52.5161363397466},{"id":83811523,"name":"Alliierten-Museum","url":"http://www.alliiertenmuseum.de/","lon":13.2723870025997,"lat":52.4555647352739},{"id":87601076,"name":"Sammlung Scharf-Gerstenberg","url":"http://www.berlin.de/tickets/suche/ort.php?ort=7084;http://www.smb.spk-berlin.de/smb/sammlungen/details.php?lang=de&objID=12807&n=13&r=5","lon":13.297225990395,"lat":52.5191632723136},{"id":87646457,"name":"Museum Berggruen","url":"http://www.smb.museum/smb/sammlungen/details.php?lang=de&objectId=22&n=1&r=12","lon":13.295039405256,"lat":52.5190991466351},{"id":93657835,"name":"Heimatmuseum","url":"http://heimatverein.teltow.de/heimatmuseum-teltow-aeltestes-haus.html","lon":13.2613798970354,"lat":52.4022393513897},{"id":93942770,"name":"Bröhan-Museum","url":"http://www.broehan-museum.de/","lon":13.2953430870309,"lat":52.5186305501298},{"id":104991250,"name":"Bodemuseum","url":"http://www.visitberlin.de/de/ort/bode-museum","lon":13.394323905151,"lat":52.5219076199488},{"id":120447353,"name":"Märkisches Museum","url":"http://www.stadtmuseum.de/index3.php?museum=mm","lon":13.4147756479837,"lat":52.5135257325173},{"id":130433320,"name":"Luftwaffenmuseum der Bundeswehr","url":"http://www.Luftwaffenmuseum.com","lon":13.1404272643009,"lat":52.4727577983473},{"id":131487807,"name":"Max-Liebermann-Haus","url":"http://www.stiftung.brandenburgertor.de/stiftung/liebermann_haus","lon":13.3778290059608,"lat":52.5167035692929},{"id":174285355,"name":"Jüdisches Museum","url":"http://www.jmberlin.de","lon":13.3961442780818,"lat":52.5018237192202},{"id":175149971,"name":"DDR-Museum","url":"http://www.ddr-museum.de","lon":13.40245015,"lat":52.51916135},{"id":182553889,"name":"Schwerbelastungskörper","url":"http://www.schwerbelastungskoerper.de","lon":13.3715497617704,"lat":52.484025190794},{"id":184592746,"name":"Museum für Architekturzeichnung","url":"http://www.tchoban-foundation.de/","lon":13.4100299295074,"lat":52.5320707889862},{"id":199532111,"name":"Industriesalon Schöneweide","url":"www.industriesalon.de","lon":13.5180057,"lat":52.46032445},{"id":277961472,"name":"Jagdschloss Grunewald","url":"http://www.spsg.de/index.php?id=140","lon":13.2619698137898,"lat":52.4674283415068},{"id":285972948,"name":"Ephraim-Palais Stadtmuseum Berlin","url":"http://www.stadtmuseum.de/ephraim-palais","lon":13.4071270316785,"lat":52.5158562236628},{"id":252550890,"name":"The Story of Berlin","url":"http://www.story-of-berlin.de","lon":13.3235264,"lat":52.5011348},{"id":260763484,"name":"Deutsches Historisches Museum","url":"http://www.dhm.de","lon":13.3969544,"lat":52.5181006},{"id":260768839,"name":"Deutsche Kinemathek - Museum für Film und Fernsehen","url":"http://www.deutsche-kinemathek.de/","lon":13.37351,"lat":52.5096032},{"id":269691877,"name":"Bauhaus Archiv","url":"http://www.bauhaus.de","lon":13.353876,"lat":52.5061895},{"id":281391655,"name":"Stasimuseum","url":"http://www.stasimuseum.de/","lon":13.4875353,"lat":52.5145119},{"id":292738889,"name":"Museum für Kommunikation","url":"http://www.mfk-berlin.de/","lon":13.3872552,"lat":52.5099308},{"id":340388625,"name":"Dalí-Museum","url":"http://www.daliberlin.de/","lon":13.378434,"lat":52.5087884},{"id":355500002,"name":"Erinnerungsstätte Notaufnahmelager Marienfelde","url":"www.notaufnahmelager-berlin.de","lon":13.3684502,"lat":52.4204028},{"id":410940703,"name":"S-Bahn-Museum","url":"http://www.s-bahn-museum.de","lon":13.12997,"lat":52.3949992},{"id":411855495,"name":"Deutsches Currywurst Museum Berlin","url":"http://currywurstmuseum.com","lon":13.3914026,"lat":52.508782},{"id":448810258,"name":"Puppentheater-Museum Berlin","url":"http://www.puppentheater-museum.de","lon":13.4389855,"lat":52.4772885},{"id":507083358,"name":"Heimatmuseum Zehlendorf","url":"http://www.heimatmuseum-zehlendorf.de","lon":13.260326,"lat":52.4354436},{"id":530775817,"name":"Deutsch-Russisches Museum Berlin-Karlshorst","url":"http://www.museum-karlshorst.de","lon":13.5396824,"lat":52.4862994},{"id":538692583,"name":"Museum für Naturkunde","url":"http://www.naturkundemuseum-berlin.de","lon":13.3791152,"lat":52.5304903},{"id":540687675,"name":"Hanf Museum Berlin","url":"http://www.hanfmuseum.de","lon":13.408184,"lat":52.5166269},{"id":545060231,"name":"Hugenottenmuseum Berlin","url":"http://www.berlin.de/orte/museum/hugenottenmuseum/","lon":13.3924292,"lat":52.514289},{"id":545074057,"name":"Historische Ausstellung des Dt. Bundestages","url":"http://www.bundestag.de/kulturundgeschichte/ausstellungen/wege/index.html","lon":13.3927272,"lat":52.5126755},{"id":545738013,"name":"Saarländische Galerie","url":"http://www.saarlaendische-galerie.eu","lon":13.395823,"lat":52.518549},{"id":632148988,"name":"Kreuzberg Museum","url":"http://www.kreuzbergmuseum.de","lon":13.4182586,"lat":52.5006123},{"id":634804367,"name":"Energie-Museum","url":"http://www.energie-museum.de/","lon":13.3301968,"lat":52.4433752},{"id":661126964,"name":"Keramik-Museum Berlin","url":"www.keramik-museum-berlin.de","lon":13.3039934,"lat":52.5171467},{"id":663295703,"name":"Labyrinth Kindermuseum","url":"http://www.labyrinth-kindermuseum.de/","lon":13.3859968,"lat":52.556125},{"id":703607134,"name":"Heimatmuseum (Mitte Museum am Gesundbrunnen)","url":"http://www.mittemuseum.de/","lon":13.3800105,"lat":52.5510701},{"id":766728477,"name":"Berliner Unterwelten","url":"http://www.berliner-unterwelten.de/fichtebunker.330.0.html","lon":13.4125151,"lat":52.4903183},{"id":766875174,"name":"Anna-Seghers-Gedenkstätte","url":"www.anna-seghers.de/gedenkstaette.php","lon":13.5407192,"lat":52.4381707},{"id":1257857022,"name":"Stadthaus","url":"http://www.museum-lichtenberg.de","lon":13.4806887,"lat":52.5029062},{"id":1260572076,"name":"Dauerausstellung \"Die Pankower Machthaber\"","url":"http://www.pankower-machthaber.de/","lon":13.4062041,"lat":52.5763714},{"id":1260572083,"name":"Dauerausstellung \"Die Pankower Machthaber\"","url":"http://www.pankower-machthaber.de/","lon":13.4063999,"lat":52.5764024},{"id":1270188822,"name":"Computerspielemuseum Berlin","url":"http://www.computerspielemuseum.de","lon":13.4419395,"lat":52.5175757},{"id":1358325721,"name":"Berliner U-Bahn Museum","url":"www.ag-berliner-u-bahn.de","lon":13.2499733,"lat":52.5173541},{"id":1387498130,"name":"Aedes Gallery","url":"http://www.aedes-arc.de/","lon":13.4108887,"lat":52.5321702},{"id":1390712121,"name":"Das Verborgene Museum","url":"http://www.dasverborgenemuseum.de/","lon":13.3184593,"lat":52.5080398},{"id":1433855703,"name":"1. Berliner DDR Motorrad-Museum","url":"http://www.erstesberliner-ddr-motorradmuseum.de","lon":13.4077402,"lat":52.5229688},{"id":1476011662,"name":"Zille-Museum","url":"http://zillemuseum-berlin.de/","lon":13.4061155,"lat":52.516433},{"id":1831591396,"name":"Martin-Gropius-Bau","url":"http://gropiusbau.de","lon":13.3819927,"lat":52.5067032},{"id":1860480265,"name":"Hamburger Bahnhof - Museum für Gegenwart","url":"http://www.hamburgerbahnhof.de","lon":13.3720175,"lat":52.5284267},{"id":1867566597,"name":"Forum Willy Brandt","url":"http://www.willy-brandt.de/forum-berlin.html","lon":13.3832985,"lat":52.5169366},{"id":1874529831,"name":"Kommunale Galerie Berlin","url":"http://www.kommunalegalerie-berlin.de/","lon":13.3120475,"lat":52.4894924},{"id":1995082505,"name":"Ethnologisches Museum","url":"http://www.smb.museum/em","lon":13.2922302,"lat":52.4567372},{"id":2272746071,"name":"Effizienzhaus Plus","url":"http://www.bmvbs.de","lon":13.3293455,"lat":52.5091155},{"id":2321948745,"name":"Uhrenmuseum","url":"http://juwelier-lorenz.de/uhrenmuseum.html","lon":13.3340061,"lat":52.4699552},{"id":2323962542,"name":"Ausstellung zur Berliner Märzrevolution","url":"http://www.friedhof-der-maerzgefallenen.de/","lon":13.4365732,"lat":52.5241696},{"id":2401869345,"name":"Mauermuseum – Haus am Checkpoint Charlie","url":"http://www.mauermuseum.de/","lon":13.3906746,"lat":52.5075162},{"id":2417322422,"name":"asisi-Panometer Berlin","url":"http://www.asisi.de/index.php?id=7#asisi_index_id_71","lon":13.3893331,"lat":52.507892},{"id":2429461877,"name":"Buchstabenmuseum","url":"www.Buchstabenmuseum.de","lon":13.4195991,"lat":52.5154563},{"id":2437533571,"name":"Aquadom","url":"www.visitsealife.com/berlin/","lon":13.40269,"lat":52.5196002},{"id":2807497298,"name":"Lippenstiftmuseum","url":"http://www.lippenstiftmuseum.de","lon":13.3340545,"lat":52.4883021},{"id":2807527330,"name":"Werkbundarchiv – Museum der Dinge","url":"http://www.museumderdinge.de","lon":13.4207946,"lat":52.5010399},{"id":2807538150,"name":"Museumswohnung","url":"http://www.stadtundland.de/33_museumswohnung.htm","lon":13.5929329,"lat":52.5343019},{"id":2807587974,"name":"Museum der Unerhörten Dinge","url":"http://www.museumderunerhoertendinge.de","lon":13.3586756,"lat":52.4869923},{"id":2818117012,"name":"Schwules Museum","url":"http://www.schwulesmuseum.de","lon":13.3582193,"lat":52.5042512},{"id":2889093537,"name":"Mampemuseum","url":"http://www.mampemuseum.de/index.html","lon":13.447389,"lat":52.4749946}];

    $(document).ready(function () {
        var infowindow = new google.maps.InfoWindow();
        var traveltime = 20;
        // Coordinates to center the map
        var myLatlng = new google.maps.LatLng(52.51, 13.37);

        // Other options for the map, pretty much selfexplanatory
        var mapOptions = {
            zoom: 13,
            center: myLatlng,
            zoomControl: true,
            disableDefaultUI: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        // Attach a map to the DOM Element, with the defined settings
        var map = new google.maps.Map(document.getElementById("map"), mapOptions);

        // init the first marker
        marker = new google.maps.Marker({
            position: myLatlng,
            draggable: true,
            map: map
        });

        // Add a basic style.
        map.data.setStyle(function(feature) {
          return /** @type {google.maps.Data.StyleOptions} */({
            icon: {
              path: google.maps.SymbolPath.CIRCLE,
              scale: 6,
              fillColor: '#00838f',
              fillOpacity: 1,
              strokeWeight: 1,
              strokeColor: '#fff'
            }
          });
        });

        map.data.addListener('click', function(event){
            var props = event.feature.f;
            infowindow.setContent('<p><strong>' + props.name + 
                '</strong></p><p><a target = "_blank" href="' + props.url + 
                    '">url</a></p><p>Travel Time: ' + Math.round((props.travelTime / 60)*100)/100 + ' minutes</p>');
            infowindow.setPosition(event.feature.getGeometry().get());
            infowindow.open(map);
        })



        // attach the click listeners, action when drag finished
        google.maps.event.addListener(marker, 'dragend', function (event) {
            filter();
        });

        var filter = function () {
            // we only want to make the request if the travel time
            // does not change for at least 100 ms
            clearTimeout(filterTimeout);

            var filterTimeout = setTimeout(function () {
                // you need to define some options for the polygon service
                // for more travel options check out the other tutorials
                var travelOptions = r360.travelOptions();
                // please contact us and request your own key
                travelOptions.setServiceKey('__APIPLACEHOLDER__');
                // set the service url for your area
                travelOptions.setServiceUrl('https://api.targomo.com/westcentraleurope/');
                // we only have one source which is the marker we just added
                travelOptions.addSource({ lat: marker.position.lat(), lng: marker.position.lng() });
                // add all the museums to the options
                travelOptions.setTargets(museumsBB);
                // set the travel type to transit
                travelOptions.setTravelType('bike');
                // for all museums which are not reachable within <maxRoutingTime>
                // no routing time will be returned
                travelOptions.setMaxRoutingTime(traveltime * 60);

                // call the service
                r360.TimeService.getRouteTime(travelOptions, function (sources) {
                    map.data.forEach(function(feature){
                        map.data.remove(feature);
                    })

                    museumsBB.forEach(function(museum){
                        museum.travelTime = null;
                    })

                    // get each target for the first source (only one source was supplied to the service)
                    sources[0].targets.forEach(function (target) {

                        // find the museum in our "database"
                        var museum = museumsBB.filter(function (museum) {
                            return museum.id == target.id; // Filter out the appropriate one
                        })[0];

                        // set the travel time for this museum
                        museum.travelTime = target.travelTime;

                    });

                    var filteredPoints = {
                        "type": "FeatureCollection",
                        "features": museumsBB.filter(function(point){
                            return point.travelTime && (point.travelTime <= (traveltime * 60));
                        }).map(function(point){
                            return {
                                "type": "Feature",
                                "properties": {
                                    "name": point.name,
                                    "url": point.url,
                                    "travelTime": point.travelTime
                                },
                                "geometry": {
                                    "type": "Point",
                                    "coordinates": [
                                        point.lon,
                                        point.lat
                                    ]
                                }
                            }
                        })
                    }
                    map.data.addGeoJson(filteredPoints);
                });
            }, 10)
        }

        // initial filter
        filter();

        // set up slider
        var sliderMax = 30;
        var travelSlider = new Dragdealer('slider', {
            steps: 7, // only select at defined intervals
            snap: true, // snap to each step
            x: traveltime / sliderMax, // set start position
            animationCallback: function (x, y) { // on slider move
                // get converted slider value
                var sliderValue = Math.round(x * sliderMax);
                // set display value
                $('#actual-time').text(sliderValue);
                // update travel time to slider position
                traveltime = sliderValue;
                // re-filter points
                filter();
            }
        });
    });
  </script>
</body>
</html>