3

I am trying to have multiple labels on a non-geographic map (image), but when I zoom in and out, I would like the text to grow and shrink in size corresponding to the zooming.

Here is what I have:

JS

 var mapExtent = [0.00000000, -16384.00000000, 16384.00000000, 0.00000000];
 var mapMinZoom = 0;
 var mapMaxZoom = 6;
 var mapMaxResolution = 1.00000000;
 var mapMinResolution = Math.pow(2, mapMaxZoom) * mapMaxResolution;;
 var tileExtent = [0.00000000, -16384.00000000, 16384.00000000, 0.00000000];
 var crs = L.CRS.Simple;
 crs.transformation = new L.Transformation(1, -tileExtent[0], -1, tileExtent[3]);
 crs.scale = function(zoom) {
   return Math.pow(2, zoom) / mapMinResolution;
 };
 crs.zoom = function(scale) {
   return Math.log(scale * mapMinResolution) / Math.LN2;
 };
 var layer;
 var map = new L.Map('map', {
   maxZoom: mapMaxZoom,
   minZoom: mapMinZoom,
   crs: crs
 });


 layer = L.tileLayer('{z}/{x}/{y}.png', {
   minZoom: mapMinZoom,
   maxZoom: mapMaxZoom,
   noWrap: true,
   tms: false,

 }).addTo(map);
 map.fitBounds([
   crs.unproject(L.point(mapExtent[2], mapExtent[3])),
   crs.unproject(L.point(mapExtent[0], mapExtent[1]))
 ]);
 L.control.mousePosition().addTo(map)


 var yx = L.latLng;
 var xy = function(x, y) {
   if (L.Util.isArray(x)) { // When doing xy([x, y]);
     return yx(x[1], x[0]);
   }
   return yx(y, x); // When doing xy(x, y);
 };


 L.marker(xy(-5213, 57.0), {
   icon: L.divIcon({
     className: 'text-labels',
     html: 'Testing a long sentence here'
   }),
 }).addTo(map);
 L.marker(xy(-3213, 57.0), {
   icon: L.divIcon({
     className: 'text-labels',
     html: 'Image 2'
   }),
 }).addTo(map);
 L.marker(xy(-5213, -1057.0), {
   icon: L.divIcon({
     className: 'text-labels',
     html: 'Image 3'
   }),
 }).addTo(map);
 L.marker(xy(-10213, 3057.0), {
   icon: L.divIcon({
     className: 'text-labels',
     html: 'Image 4'
   }),
 }).addTo(map);
 L.marker(xy(10213, -5057.0), {
   icon: L.divIcon({
     className: 'text-labels',
     html: 'Image 5'
   }),
 }).addTo(map);

CSS

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

#slider {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 5;
}

#map {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  z-index: 0;
  background: none;
}

.text-labels {
  font-size: 1em;
  font-weight: 700;
  cursor: grab;
  white-space: nowrap;
}

Here is a fiddle

1

One way to achieve this is to change font size of .text-labels CSS class dynamically at the end of each zoom.

To change font size of .text-labels CSS class relevant style is needed. I once found function getStyle on Stack Overflow (forgoten where) that does just that: gets style object for given CSS class. Probably overkill in this case, but it works.

From here on it's easy: just use map zoomend event to dynamically change font size at the end of each zoom. Relation between zoom and font size is then just matter of formula, which can be any.

Code (which goes to the end) then looks like this:

// Function to get style of select CSS class
function getStyle(ruleClass) {
  for (var s = 0; s < document.styleSheets.length; s++) {
    var sheet = document.styleSheets[s];
    if (sheet.href == null) {
      var rules = sheet.cssRules ? sheet.cssRules : sheet.rules;
      if (rules == null) return null;
      for (var i = 0; i < rules.length; i++) {
        if (rules[i].selectorText == ruleClass) {
            return rules[i].style;
        }
      }
    }
  }
  return null;
}

var markerTextStyle = getStyle('.text-labels');

// Set font size for givem zoom
function setMarkerTextSize(zoom) {
  markerTextStyle.fontSize = 12 + ((zoom - 1) * 4) + 'px';
}

// Set inital font size
setMarkerTextSize(map.getZoom());

map.on('zoomend', function(e) {
  setMarkerTextSize(map.getZoom());
});
  • Fantastic! Works great. Thanks @TomazicM – user2675647 Aug 1 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.