/ JavaScript

Good coffee shops in London and how to place them on the map

Scientists not sure whether the coffee is good or bad for health. However, and that's for sure, a good coffee is much better than a bad coffee. Coffee shop is not only about the coffee, it is also about the nice talks and friendly environment. This page is about my favourite coffee shops. Specifically it is about map of them, created with Leaflet and OpenStreetMap. You can use the same approach to create list of your favoirite places.

If you are here for the map, you can jump right away to it.

The engine of the map is Leaflet - "the leading open-source JavaScript library for mobile-friendly interactive maps". It displays map, which you can zoom in/out, grag, add markers, draw over it, etc. Leaflet itself is a library, it is need to be pointed to a data source with map tiles (images) to draw the map. The map tiles server I'm going to use is from OpenStreetMap.

The following HTML page inclues Leaflet styles and scripts and zooms on London. It can be just saved and opened in the browser.

<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css"
  integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ=="
  crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"
  integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log=="
  crossorigin=""></script>
<style>
html, body { height : 100%; padding: 0; margin: 0; }
#mapid { height: 100%; }
</style>
<script>
window.onload = function () {
    var canvas = L.canvas();
    var map = L.map('mapid').setView([51.505, -0.09], 13);
    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18 }).addTo(map);
};
</script>
</head>
<body><div id="mapid"></div></body>
</html>

The points of interests can be displayed as markers on the map. Although there are many ways to add the markers, the most efficient one is to add them through circleMarkers. The new marker can be added as follows:

L.circleMarker(
  [ 51.5236441843013, -0.0824280755028865 ],
  { radius : 3 }
).addTo(map)
  .bindPopup('tailor st. baristas - they have not a bad coffee, actually');

The list of coffee shops can be stored in many different ways. I prefer a simple CSV file with the name, notes, post code and optional location. Like this:

Wild & Wood Coffee;next to Ryman, good place to have a chat;EC2M 5TE;51.5170360903313,-0.0880241541382084

However, it is much simpler to use objects, so let's convert:

function converDataLine(line) {
  var parts = line.split(/;/);
  var result = { name : parts[0], notes : parts[1], postcode : parts[2] };
  var location = parts[3].split(/,/);
  if (location.length === 2) {
      result.location = { lon : location[0], lat : location[1] };
  }
  return result;
}

The data file can be requested with JSON call and then converted to markers:

<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script>
<script>
$(() => {
  $.ajax({ url : "coffee.shops.csv", dataType : "text" })
    .done(data => {
      var shops = data.split(/\n/)
        .filter(line => line !== "")
        .map(converDataLine);
        
      var canvas = L.canvas();
      var map = L.map('mapid').setView([51.505, -0.09], 13);
      L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18 }).addTo(map);
      
      shops.forEach(shop => {
        L.circleMarker(
          [ shop.location.lat, shop.location.lon ],
          { radius : 3 }
        ).addTo(map)
          .bindPopup(shop.name + '\n' + shop.notes + '\n' + shop.postcode);
      });
    });
});
</script>

BTW, the list is not complete, more to come...

Alex Netkachov

Alex Netkachov

Alex likes functional programming and algorithms. Apart from programming, his favourites are walking with his family in the parks and national trails and reading about universe and history.

Read More