So I'm using the latest version of leaflet (v1.0.2), and am trying to dynamically apply text labels to specific lat lng points on a custom (geo aligned) map.
My issue is that I need the text on the map to maintain it's the size (as though the text is actually part of the tile image) when zooming. Using a Marker of any kind results in the text staying at its correct size. If I use something like an image overlay and add an SVG with text in, it scales with the map zoom.
I've noticed that the image overlay has a CSS3 scale added to its transform property when zooming whereas the marker does not.
Can I extend the marker to scale as the image overlay does?
I've already written code that listens to the zoom event and adjusts the font size of markers but this is CPU intensive (especially for mobile browsers) and I don't really want to render the text dynamically within svgs either!
I've provided a demo so that this makes more sense. You can see that example_1 (the marker) maintains it's size however far you zoom in or out. Example_2 (the svg image) scales relative to the map when zooming. This (Example_2) is what I'm trying to get an L.DivIcon with html text content to do!
Any help or suggestions are appreciated!
https://jsfiddle.net/z96L7hdu/
Example Code
HTML
<div id="map" style="width:500px; height:600px;"></div>
JavaScript
var map = L.map('map', {
zoomSnap: 0
}).setView([0, 0], 3);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var img = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciICAgICB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgNTAwIDQwIj4gIDx0ZXh0IHg9IjAiIHk9IjAiIGZvbnQtZmFtaWx5PSJWZXJkYW5hIiBmb250LXNpemU9IjM1Ij4gICAgRXhhbXBsZV8yICA8L3RleHQ+PC9zdmc+";
imageBounds = [[-8.636810901898114, -12.135975261193327], [-18.28136415046407, 17.181122017133486]];
L.imageOverlay(img, imageBounds).addTo(map);
var myIcon = L.divIcon({className: 'my-div-icon', html:"Example_1"});
L.marker({lat: 0.7800052024755708, lng: 0.010986328125}, {icon: myIcon}).addTo(map);
Apologies for the late answer, but I thought it was an interesting question. You can indeed extend the L.Marker
class, to create markers that resize the font of their DivIcon
to match the zoom level:
L.FixedSizeMarker = L.Marker.extend({
options: {
fontSize: 12, // starting size of icon in pixels
zoomBase: 3 // Zoom level where fontSize is the correct size
},
update: function () {
if (this._icon && this._icon.tagName === 'DIV' && this._map) {
let size = this.options.fontSize * Math.pow(2, (this._map.getZoom() - this.options.zoomBase));
this._icon.style.fontSize = size + 'px';
}
return L.Marker.prototype.update.call(this);
}
});
L.fixedSizeMarker = (latlng, options) => new L.FixedSizeMarker(latlng, options);
The code above defines a new FixedSizeMarker
, which behaves just like a normal Marker
, but if you add a DivIcon
to it, it will resize the font. It takes two options, to specify the font size in pixels, and the zoom level that you want that font size to be correct for. In the example in the OP's JSFiddle, you would use it like this:
var myIcon3 = L.divIcon({className: 'my-div-icon', html:"Example_3"});
L.fixedSizeMarker({lat: 0.7800052024755708, lng: -12.135975261193327},
{icon: myIcon3, fontSize: 24, zoomBase: 3}).addTo(map);
When using these markers, it may look better to set {markerZoomAnimation: false}
in the map options. The marker size change is otherwise quite obvious when you zoom the map.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With