Robin van der Vliet
Robin van der Vliet

Reputation: 141

Centering Leaflet divIcon marker with dynamic content

I created a simple Leaflet map with markers for some countries. Currently all the markers are not centered at their middle point, but at their top left point.

This is the code I have now:

const countries = [
  [52.32, 5.55, "🇳🇱 Netherlands"],
  [50.64, 4.67, "🇧🇪 Belgium"],
  [51, 10, "🇩🇪 Germany"],
  [47, 2, "🇫🇷 France"],
  [42.56, 1.56, "🇦🇩 Andorra"],
  [40.2, -3.5, "🇪🇸 Spain"],
  [38.7, -9.18, "🇵🇹 Portugal"],
  [52, 19, "🇵🇱 Poland"],
  [50, 16, "🇨🇿 Czechia"],
  [46.8, 8.23, "🇨🇭 Switzerland"]
];

let map = L.map("map", {
  worldCopyJump: true
}).setView({
  lat: 50,
  lon: 10
}, 5);

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  minZoom: 2,
  maxZoom: 10,
  attribution: "&copy; <a href=\"https://openstreetmap.org/copyright\">OpenStreetMap</a>"
}).addTo(map);

L.control.scale().addTo(map);

const regions = L.featureGroup().addTo(map);

countries.forEach((country) => {
  L.marker([country[0], country[1]], {
    icon: L.divIcon({
      iconSize: "auto",
      html: "<b>" + country[2] + "</b>"
    })
  }).addTo(regions);
})

map.addLayer(regions);
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}

#map {
  width: 100%;
  height: 100%;
}

.leaflet-div-icon {
  border: 1px solid #666;
  border-radius: 3px;
  padding: 3px;
  text-align: center;
}
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<link href="https://unpkg.com/[email protected]/dist/leaflet.css" rel="stylesheet" />
<div id="map"></div>

My expected result is that all div elements with the class name "leaflet-div-icon" are positioned half of their width to the left, and half of their height upwards. For example, look at Andorra, currently only the top left point of the marker is in Andorra, and the rest is outside it. I would like the middle point of the marker to be in Andorra.

I tried adding the following code, but this moves all markers in a wrong position:

.leaflet-div-icon {
    position: relative;
    top: -50%;
    left: -50%;
}

Upvotes: 4

Views: 11774

Answers (1)

Kosh
Kosh

Reputation: 18393

You might override the default .leaflet-div-icon style, and then style its child b to look and be placed as you'd like:

const countries = [
  [52.32, 5.55, "&#127475;&#127473;&nbsp;Netherlands"],
  [50.64, 4.67, "&#127463;&#127466;&nbsp;Belgium"],
  [51, 10, "&#127465;&#127466;&nbsp;Germany"],
  [47, 2, "&#127467;&#127479;&nbsp;France"],
  [42.56, 1.56, "&#127462;&#127465;&nbsp;Andorra"],
  [40.2, -3.5, "&#127466;&#127480;&nbsp;Spain"],
  [38.7, -9.18, "&#127477;&#127481;&nbsp;Portugal"],
  [52, 19, "&#127477;&#127473;&nbsp;Poland"],
  [50, 16, "&#127464;&#127487;&nbsp;Czechia"],
  [46.8, 8.23, "&#127464;&#127469;&nbsp;Switzerland"]
];

let map = L.map("map", {
  worldCopyJump: true
}).setView({
  lat: 50,
  lon: 10
}, 5);

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  minZoom: 2,
  maxZoom: 10,
  attribution: "&copy; <a href=\"https://openstreetmap.org/copyright\">OpenStreetMap</a>"
}).addTo(map);

L.control.scale().addTo(map);

const regions = L.featureGroup().addTo(map);

countries.forEach((country) => {
  L.marker([country[0], country[1]], {
    icon: L.divIcon({
      iconSize: "auto",
      html: "<b>" + country[2] + "</b>"
    })
  }).addTo(regions);
})

map.addLayer(regions);
html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}

#map {
  width: 100%;
  height: 100%;
}

#map .leaflet-div-icon {
  width:0;
  height:0;
  border: 0;
  padding: 0;
}

#map .leaflet-div-icon b {
  display:inline-block;
  padding: 3px;
  border: 1px solid #666;
  border-radius: 3px;
  background:#fff;
  transform:translate(-50%, -50%);
}
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<link href="https://unpkg.com/[email protected]/dist/leaflet.css" rel="stylesheet" />
<div id="map"></div>

Upvotes: 7

Related Questions