spinkus
spinkus

Reputation: 8550

Leaflet small divIcons less than 14px do not align at center of point

I want to add some very small custom divIcon markers to a Leaflet (v1.9.3) map. However, it seems icons smaller than [14,14] do not align at the center of the marker. Following image shows three markers at same location with a circle SVG as the divIcon and radii of 50,20,6. Notice the first two center but the 6px one is off center:

enter image description here

Some control can be had with iconAnchor but seems the value would need to vary depending on iconSize and the computation isn't obvious to me. Is there a better way to center align small divIcons like above?

Code for above image:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    <style type='text/css'>
      html, body { margin: 0; padding: 0; border: 0; }
      #map { height: 100vh; }
    </style>
    <script>
      var map;
      var myIcon = (color = 'red', b = 24) => `
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${b} ${b}">
    <circle fill="${color}" cx="${b/2}" cy="${b/2}" r="${b/2}" />
  </svg>`;
      function init() {
        var map = L.map('map').setView([50.0, 0.0], 13);
        L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          maxZoom: 18
        }).addTo(map);
        var marker = L.marker(
          [51.5, -0.09], {
          icon: L.divIcon({
            html: myIcon('red', 50),
            iconSize: [50,50],
            className: ''
          }),
        }).addTo(map);
        var marker = L.marker(
          [51.5, -0.09], {
          icon: L.divIcon({
            html: myIcon('green', 20),
            iconSize: [20,20],
            className: ''
          }),
        }).addTo(map);
        var marker = L.marker(
          [51.5, -0.09], {
          icon: L.divIcon({
            html: myIcon('blue', 6),
            iconSize: [6,6],
            className: ''
          }),
        }).addTo(map);
        map.panTo(marker.getLatLng());
      }
    </script>
  </head>
  <body onload='init();'>
    <div id="map"></div>
  </body>
</html>

Upvotes: 0

Views: 116

Answers (1)

simon04
simon04

Reputation: 3312

Solution: set style="display: block" on the <svg> element. <svg> elements are use display: inline by default which uses some flow layouting algorithm.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 6" style="display: block">
    <circle fill="blue" cx="3" cy="3" r="3"></circle>
</svg>

Upvotes: 1

Related Questions