Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Leaflet: Fit Polyline in View

DZone's Guide to

Leaflet: Fit Polyline in View

We take a look at using Leaflet.js to help visualize a route on a map with the ability to ensure that the map is zoomed to show all of the points on a given route.

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

I’ve been playing with the Leaflet.js library over the Christmas holidays to visualize running routes drawn onto the map using a Polyline and I wanted to zoom the map the right amount to see all the points.

Pre-Requisites

We have the following HTML to define the div that will contain the map.

<div id="container">
	<div id="map" style="width: 100%; height: 100%">
	</div>
</div>

We also need to import the following JavaScript and CSS files:

<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
  <script type="text/javascript" src="https://rawgit.com/jieter/Leaflet.encoded/master/Polyline.encoded.js"></script>
  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"/>

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.css"/>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.js"></script>

Polyline Representing Part of a Route

The following code creates a polyline for a Strava segment that I often run.

var map = L.map('map');
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom: 18,}).addTo(map);

var rawPoints = [
  { "latitude": 51.357874010145395, "longitude": -0.198045110923591 },
  { "latitude": 51.3573858289394, "longitude": -0.19787754933584795 },
  { "latitude": 51.35632791810057, "longitude": -0.19750254941422557 },
  { "latitude": 51.35553240304241, "longitude": -0.197232163894512 },
  { "latitude": 51.35496267279901, "longitude": -0.1970247338143316 },
  { "latitude": 51.35388700570004, "longitude": -0.19666483094752069 },
  { "latitude": 51.3533898352570, "longitude": -0.1964976504847828 },
  { "latitude": 51.35358452733139, "longitude": -0.19512563906602554 },
  { "latitude": 51.354762877995036, "longitude": -0.1945622934585907 },
  { "latitude": 51.355610110109986, "longitude": -0.19468697186046677 },
  { "latitude": 51.35680377680643, "longitude": -0.19395063336295112 },
  { "latitude": 51.356861596801075, "longitude": -0.1936180154828497 },
  { "latitude": 51.358487396611125, "longitude": -0.19349660642888197 }
];

var coordinates = rawPoints.map(rawPoint => new L.LatLng(rawPoint["latitude"], rawPoint["longitude"]))

let polyline = L.polyline(
    coordinates,
    {
        color: 'blue',
        weight: 3,
        opacity: .7,
        lineJoin: 'round'
    }
);

polyline.addTo(map);

I wanted to center the map around the polyline and initially wrote the following code to do this:

let lats = rawPoints.map(c => c.latitude).reduce((previous, current) => current += previous, 0.0);
let longs = rawPoints.map(c => c.longitude).reduce((previous, current) => current += previous, 0.0);

const position = [lats / rawPoints.length, longs / rawPoints.length];
map.setView(position, 17);

This works fine but the zoom factor was wrong when I drew longer polylines so I needed a better solution.

I should have RTFM because there’s a much simpler way to do this. I actually found the explanation in a GitHub issue from 2011! We can replace the previous snippet with this single line of code:

map.fitBounds(polyline.getBounds());

And this is how it looks on the screen:

2017 12 31 17 30 25

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
javascript ,leaflet ,web dev ,javascript library

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}