Filter Points of Interest by travel time

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

Since the TimeService returns precise travel times to all targets, we can symbolize by color ramps, thus showing relative distance by target color/shade.

Symbolize 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
reload
open in new tab
copy HTML
hide code
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <!--  Include leaflet javascript and css -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" crossorigin="">
  <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" crossorigin=""></script>
  <!-- D3 libs for colors and interpolation  -->
  <script src="https://d3js.org/d3-color.v1.min.js"></script>
  <script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
  <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
  <!--  Include r360.js -->
  <script src="https://releases.route360.net/r360-js/latest.js"></script>

  <style>
    html, body { width: 100%; height: 100%; margin: 0; font-family: sans-serif; }
    #map { width: 100%; height: 100%; }
    .leaflet-popup-content-wrapper {
      padding: 1px;
      text-align: left;
      border-radius: 0px !important;
      box-shadow: none !important;
      padding: 3% !important;
    }
    .leaflet-popup-content-wrapper a { color: black !important; }
    #select {
      position: absolute;
      top: 10px;
      right: 10px;
    }
  </style>
</head>
<body>
  <!--  where the map will live  -->
  <div id="map"></div>
  <select id="select"></select>
  
  <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}];
    // container for museum markers
    var targets = [];
    var traveltime = 30;
    // define a pair of coordinates, where the map should be centered
    var latlon = [52.51, 13.37];

    // add the map and set the initial center to berlin
    var map = L.map('map', { zoomControl: false }).setView(latlon, 12);
    map.attributionControl.addAttribution("ÖPNV Daten © <a href='https://www.vbb.de/de/index.html' target='_blank'>VBB</a>");

    // create empty layer to put results into
    var targetLayer = L.featureGroup().addTo(map);

    // put zoom controls at the bottom
    L.control.zoom({ position: 'bottomleft' }).addTo(map);

    // initialise the base map
    r360.basemap({ style: 'basic', apikey: '__APIPLACEHOLDER__' }).addTo(map);

    // create the filter start marker
    var sourceMarker = L.marker((latlon), { draggable: true, zIndexOffset: 1000 }).addTo(map);

    var symbolize = function(interpolator) {
      // you need to define some options for the polygon service
      // for more travel options check out the other tutorials
      var travelOptions = r360.travelOptions();
      // we only have one source which is the marker we just added
      travelOptions.addSource(sourceMarker);
      // add all the museums to the options
      travelOptions.setTargets(targets);
      // 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);

      // set the service API-key
      travelOptions.setServiceKey('__APIPLACEHOLDER__');
      travelOptions.setServiceUrl('https://api.targomo.com/westcentraleurope/');

      // call the service
      r360.TimeService.getRouteTime(travelOptions, function(sources) {

        targetLayer.clearLayers();

        // 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 poiSymbol = getSymbol(museum, museum.travelTime, travelOptions.getMaxRoutingTime(), interpolator);

          // bind the popup
          bindPopup(poiSymbol, museum);

          // add to targetLayer
          poiSymbol.addTo(targetLayer);
        });
      });
    }

    // symbology definition function
    var getSymbol = function(point, distance, maxdist, interpolator){
      var scaleVal = 1 - (distance / maxdist);
      var rgb = d3.rgb(d3[interpolator](scaleVal));
      return L.circleMarker([point.lat, point.lon], {
        color: distance < 0 ? 'rgba(0,0,0,.5)' : 'white',
        fillColor: distance < 0 ? 'rgba(255,255,255,.6)' : rgb,
        fillOpacity: 1.0,
        stroke: true,
        radius: distance < 0 ? 4 : 6,
      })
    }

    // popup binding function
    var bindPopup = function(poiSymbol, point){
      var popUpContent = "<h2><a href='" + point.url + "'>" + point.name + "</a></h2>";
      if (point.travelTime > 0){
        popUpContent += "<p> Travel time: " + r360.Util.secondsToHoursAndMinutes(point.travelTime) + "</p>"
      };
      poiSymbol.bindPopup(popUpContent);
    }

    // populate layer from museumsBB source, no distances so will defaul to grey
    var loadTargets = function(callback) {
      targets = [];
      museumsBB.forEach(function(museum) {
        var target = L.circleMarker(museum);
        target.id = museum.id;
        targets.push(target);
      });

      callback();
    }

    // name,display
    var interpolators = [
      ['RedYellowGreen','interpolateRdYlGn'],
      ['Spectral','interpolateSpectral'],
      ['YellowOrangeRed','interpolateYlOrRd'],
      ['PurpleRed','interpolatePuRd'],
      ['Greens','interpolateGreens'],
      ['Greys','interpolateGreys']
    ]

    // initial load
    loadTargets(function(){
      symbolize(interpolators[0][1],interpolators[0][2]);
    });

    for (var i = 0; i < interpolators.length; i++){
     var option = $('<option></option>');
     option.val(interpolators[i][1]);
     option.html(interpolators[i][0]);
     $('#select').append(option);
    }

    $('#select').change(function(){
      var selected = $(this).find(':selected');
      symbolize(selected.val());
    });

    // re-filter on marker drag
    sourceMarker.on('dragend', symbolize);
  </script>
</body>
</html>