svoop
svoop

Reputation: 3454

Apply "vector" to Point or LatLng in Leaflet

Drawing e.g. a 4km radius circle on a Leaflet map is dead simple. However, labelling that circle (without plugins) is not that simple anymore. The following fiddle somewhat works, but the 4km label dances around as you change zoom levels:

https://jsfiddle.net/svoop/y1jqoxu7/

Any idea how I could improve this?

(Please don't suggest any plugins unless they are very well maintained and ready for Leaflet 1.0, thanks!)

Upvotes: 1

Views: 268

Answers (1)

nathansnider
nathansnider

Reputation: 2873

The label in your example is offset because you are calculating meters/pixel in an unreliable way. There is no guarantee that centerLatLng falls exactly at the center of a pixel on the map. In fact, it is almost guaranteed not to, so map.containerPointToLatLng([centerPoint.x, centerPoint.y]) will not produce the same coordinates as centerLatLng, and your distances will be off by as much as 50%. You will get a more satisfactory result by calculating your metersPerPixelY like this:

metersPerPixelY = map.containerPointToLatLng([centerPoint.x, centerPoint.y + 1]).distanceTo(map.containerPointToLatLng([centerPoint.x, centerPoint.y]));

However, there will still be some error with this method, as the true meters/pixel varies with latitude. My suggestion would be to use leaflet-geodesy to create ~circular polygons and place your labels based on the bounds of those polygons. L.circle objects do not provide any method to get their bounds, so the plugin is necessary. The following will create a 144-sided polygon (fine enough to look circular at any scale) and place a label on the northern edge of the circle:

var circ = LGeo.circle(centerLatLng, radiusMeters, {parts: 144}).addTo(map);
var labelLatLng = [circ.getBounds().getNorth(),centerLatLng[1]];
var labelUp = L.divIcon({ className: 'four', html: '4km' });
L.marker(labelLatLng, { icon: labelUp }).addTo(map);

This is certainly not the only way to get the label location you want, but it is relatively simple, and the plugin works fine with Leaflet 1.0. Here's an example fiddle:

http://jsfiddle.net/nathansnider/a022bL4q/

Upvotes: 1

Related Questions