13

I am trying to load a simple leaflet map in my Ionic 2 app. Unfortunately not all tiles are loaded currectly until a moving the map.

this.map = new L.Map('mainmap', {
      zoomControl: false,
      center: new L.LatLng(40.731253, -73.996139),
      zoom: 12,
      minZoom: 4,
      maxZoom: 19,
      layers: [this.mapService.baseMaps.OpenStreetMap],
      attributionControl: false
    });

enter image description here

rakete
  • 2,953
  • 11
  • 54
  • 108
  • 4
    You might be in that case: http://stackoverflow.com/questions/36246815/data-toggle-tab-does-not-download-leaflet-map/36257493#36257493 – ghybs Aug 08 '16 at 15:26

3 Answers3

11

There are a couple of solutions for this problem:

1- Add "./node_modules/leaflet/dist/leaflet.css" in the styles array in `angular.json'.

2- Invalidate size when a map is ready:

onMapReady(map: L.Map) {
    setTimeout(() => {
      map.invalidateSize();
    }, 0);
}

Add this to your template:

<div style="height: 300px;"
   leaflet
   (leafletMapReady)="onMapReady($event)">
</div>

And this will bind onMapReady method which you have in your component.

3- Install Leaflet typings for Typescript:

npm install --save-dev @types/leaflet

Vanilla JavaScript:

1- Validate the size of map:

onMapReady(map: L.Map) {
   setTimeout(() => {
     map.invalidateSize();
   }, 0);
}

2- Add leaflet stylesheet leaflet/dist/leaflet.css in the <head> of your document.

Maihan Nijat
  • 9,054
  • 11
  • 62
  • 110
  • 1
    Looks like you assume some Leaflet Angular wrapper, whereas OP initilizes their Leaflet map with vanilla JS. – ghybs Dec 04 '18 at 17:03
  • @ghybs Thanks for the hint. I edited the answer, however the solution is almost same, just difference on how to implement it. – Maihan Nijat Dec 04 '18 at 17:52
  • It is true that in 2016, Angular 2 may not have provided the `angular.json` file. But it seems to me that you should also modify the listener part: if OP does not use an Angular wrapper, they do not have `leafletMapReady` event. I would rather look at ViewChild and component lifecycle. – ghybs Dec 04 '18 at 21:38
  • Hi, I added this but its giving me the error : Cannot read property '_leaflet_pos' of undefined, Any idea why? – akshay kishore Apr 09 '19 at 10:04
  • @akshaykishore Please share your code or open a question and share it to me so I go through your code and find the cause. Thanks – Maihan Nijat Apr 09 '19 at 12:13
  • thanks for the reply @MaihanNijat, but its ok I figured it out...it was a simple syntax error from my part – akshay kishore Apr 09 '19 at 14:29
  • It has to be wrapped in a setTimout. I do not know why but that was the only way I got it working. – Dirk Schumacher Dec 21 '21 at 15:01
3

this work for me fine :

this.map = L.map('map');
const self = this;
    
this.map.on("load",function() { setTimeout(() => {
   self.map.invalidateSize();
}, 1); });
    
this.map.setView([36.3573539, 59.487427], 13);
HamidReza
  • 1,726
  • 20
  • 15
2

Just put the creation of the map into the Ionic ionViewDidEnter lifecycle method. Much cleaner than any setTimeout hack ;)

import { Map, tileLayer } from 'leaflet';

...

ionViewDidEnter(): void {
    this.map = new Map('map', {
       center: [48.1351, 11.5819],
       zoom: 3
    });

   const tiles = tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
       maxZoom: 18,
       minZoom: 3,
       attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OSM</a>'
   });

   tiles.addTo(this.map);
}
mbauer
  • 348
  • 1
  • 6
  • 25