Search code examples
angularionic-frameworkleafletionic5angular12

Leaflet + Ionic5 / Angular - Map bad Rendering -


after doing some search about it without success I come to you having known there are multiple threats about this, but as i said those haven't solved my problem.

The problem:
As other people has experienced, Leaflet has some issues with map and framework pages loading.

  • If I resize manually the browser screen it renders correctly.
  • if I reload the window the map is NOT rendered.

    Example: enter image description here

  • As you can see there are no current errors on console that may cause this issue, so let's go to the code.

    Code:


    I have some commented code, erased for this post, but as it is commented for the >ionic serve command it shouldn't affect to the execution

    @Component({
      selector: 'app-map',
      templateUrl: './map.component.html',
      styleUrls: ['./map.component.scss'],
    })
    export class MapComponent implements OnInit, AfterViewInit {
    
      serviceRequestBoundsIcon = '../../../assets/custom/map-outline.svg';
      now: Date;
      private markers: L.Marker[] = [];
      private map: L.Map;
      private iconTruck = L.icon({
        iconUrl: '../../../assets/truck-39103_1280.png',
        iconSize: [40, 20],
        iconAnchor: [20, 10],
        popupAnchor: [1, -34],
        tooltipAnchor: [16, -28],
        shadowSize: [41, 41]
      });
      private iconwatch = L.icon({
        iconUrl: '../../../assets/custom/map-outline.svg',
        iconSize: [40, 20],
        iconAnchor: [20, 10],
        popupAnchor: [1, -34],
        tooltipAnchor: [16, -28],
        shadowSize: [41, 41]
      });
      private watchSubscriber: Subscription;
    
    
    
      constructor() {
      }
    
      ngOnInit() {
        this.initMap();
        console.log('oninit');
      }
    
      ngAfterViewInit() {
        this.map.invalidateSize();
        console.log('view init');
      }
    
      private initMap(){
    
        this.map = L.map('map', {
          center: [ 49.00, 10.00 ],
          zoom: 6
        });
        const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          maxZoom: 18,
          minZoom: 3,
          attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        });
        tiles.addTo(this.map);
      }
    
    • Here I have tried moving the initMap() & the this.map.invalidateSize() to different hooks (ngAfterViewInit, ngAfterContentInit, ngOnInit, constructor), with barely the same result, sometimes it works but at reload stops working...
  • This angular map component is inside the location tab page made by ionic tabs generator, the location module has no logic on it.
  • I have also tried the MutationObserver solution founded in a post from SO. Not used by now.
    private renderMap(){
        const observer = new MutationObserver(() => {
          console.log('init mutation');
          this.map.invalidateSize();
          observer.disconnect();
          console.log('cancel observer');
        });
        console.log('init observer');
        observer.observe(document.documentElement, {
          attributes: true,
          attributeFilter: ['class'],
          childList: false,
          characterData: false,
        });
      }
    

  • Inside index.html:
  • <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/>
    
  • angular.json:
  •   "projects": {
    "app": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "www",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "assets"
              },
              {
                "glob": "**/*.svg",
                "input": "node_modules/ionicons/dist/ionicons/svg",
                "output": "./svg"
              },
              {
                "glob": "**/*",
                "input": "node_modules/leaflet/dist/images/",
                "output": "assets"
              },
              "src/manifest.webmanifest",
              "src/manifest.webmanifest",
              "src/manifest.webmanifest",
              "src/manifest.webmanifest"
            ],
            "styles": ["./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "node_modules/leaflet/dist/leaflet.css", "src/theme/variables.scss", "src/global.scss"],
            "scripts": [],
            "aot": false,
            "vendorChunk": true,
            "extractLicenses": false,
            "buildOptimizer": false,
            "sourceMap": true,
            "optimization": false,
            "namedChunks": true,
            "serviceWorker": true,
            "ngswConfigPath": "ngsw-config.json"
          },
    

    I hope i can solve this with the community help, I do not understand what can be happening here! If more details are requested please feel free to ask for them, I'll be paying attention to this post!


    Solution

  • By the moment I've been able to solve the issue adding a setTimeout(()=>{this.map.invalidateSize();},100), I'm wondering if there's a better solution for this please let me know!