Search code examples
vue.jsleafletvue2leaflet

Cannot load pixiOverlay in leaflet through vue


My leaflet maps were rendering too slow, I found pixiOverlay an alternative for that but I just cant make it run. Any example would help.

following is my component

<template>
  <div ref="mapElement" style="height: 400px;"></div>
</template>

<script>
  // import {
  //   LMap,
  //   LTileLayer
  // } from 'vue2-leaflet';
  import * as PIXI from 'pixi.js';
  import 'leaflet-pixi-overlay';
  import L from 'leaflet';

  export default {
    name: 'HelloWorld',
    components: {
      // LMap,
      // LTileLayer,
    },
    data() {
      return {
        // url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        // zoom: 3,
        // center: [47.413220, -1.219482],
        // bounds: null,
        map: L.map
      };
    },
    methods: {
      draw() {
        // this.map = L.map('map', {
        //   center: [30, 30],
        //   zoom: 13,
        // });

        var loader = new PIXI.loaders.Loader();
        loader.add('marker', 'img/marker-icon.png');
        loader.load(function(loader, resources) {
          var markerTexture = resources.marker.texture;
          var markerLatLng = [51.505, -0.09];
          var marker = new PIXI.Sprite(markerTexture);
          marker.anchor.set(0.5, 1);

          var pixiContainer = new PIXI.Container();
          pixiContainer.addChild(marker);

          var firstDraw = true;
          var prevZoom;

          var pixiOverlay = L.pixiOverlay(function(utils) {
            var zoom = utils.getMap().getZoom();
            var container = utils.getContainer();
            var renderer = utils.getRenderer();
            var project = utils.latLngToLayerPoint;
            var scale = utils.getScale();

            if (firstDraw) {
              var markerCoords = project(markerLatLng);
              marker.x = markerCoords.x;
              marker.y = markerCoords.y;
            }

            if (firstDraw || prevZoom !== zoom) {
              marker.scale.set(1 / scale);
            }

            firstDraw = true;
            prevZoom = zoom;
            renderer.render(container);
          }, pixiContainer);

          pixiOverlay.addTo(this.map);
        });
      },
      zoomUpdated(zoom) {
        this.zoom = zoom;
      },
      centerUpdated(center) {
        this.center = center;
      },
      boundsUpdated(bounds) {
        this.bounds = bounds;
      },
    },
    mounted() {
      this.map = L.map(this.$refs['mapElement']).setView([51.505, -0.09], 13);

      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 18,
      }).addTo(this.map);

      this.draw();
    },
  }
</script>

I tried using lifecycle hooks. The error I got previously was Container not found (now solved). The error now I am getting is "cannot read property of null"

Error

Update 1

<template>
<div ref="map" style="height: 400px;">

</div>
</template>

<script>

import * as PIXI from 'pixi.js';
import 'leaflet-pixi-overlay';
import L from 'leaflet';

export default {
    name: 'HelloWorld',
    
    data() {
        return {
            
            map: L.map
        };
    },
    methods: {
        draw() {
            let loader = new PIXI.Loader()
            loader.add('marker', 'https://pixijs.io/examples/examples/assets/bunny.png')
            loader.load((loader, resources) => {
                let markerTexture = resources.marker.texture
                let markerLatLng = [51.505, -0.09]
                let marker = new PIXI.Sprite(markerTexture)
                marker.anchor.set(0.5, 1)

                let pixiContainer = new PIXI.Container()
                pixiContainer.addChild(marker)

                let firstDraw = true
                let prevZoom

                let pixiOverlay = L.pixiOverlay(utils => {
                    let zoom = utils.getMap().getZoom()
                    let container = utils.getContainer()
                    let renderer = utils.getRenderer()
                    let project = utils.latLngToLayerPoint
                    let scale = utils.getScale()

                    if (firstDraw) {
                        let markerCoords = project(markerLatLng)
                        marker.x = markerCoords.x
                        marker.y = markerCoords.y
                    }

                    if (firstDraw || prevZoom !== zoom) {
                        marker.scale.set(1 / scale)
                    }

                    firstDraw = true
                    prevZoom = zoom
                    renderer.render(container)
                }, pixiContainer)

                pixiOverlay.addTo(this.map)
            })
        },
       
        zoomUpdated(zoom) {
            this.zoom = zoom;
        },
        centerUpdated(center) {
            this.center = center;
        },
        boundsUpdated(bounds) {
            this.bounds = bounds;
        },

    },
    mounted() {
        this.map = L.map(this.$refs.map).setView([51.505, -0.09], 13)

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 18,
        }).addTo(this.map)

        this.draw()
    }

}
</script>

Error


Solution

  • I think the problematic line is:

    pixiOverlay.addTo(this.map);
    

    Because you call this inside another function so that this is not reference to your component which means it's probably undefined or has another value.

    You can solve this by using arrow function:

    ...
      loader.load((loader, resources) => {
        ...
        var pixiOverlay = L.pixiOverlay((utils) => {
            ...
        }, pixiContainer)
    
        pixiOverlay.addTo(this.map);
      });
    ...
    

    JSFiddle