如何从leafletjs多边形创建离子弹出框?

时间:2018-06-25 15:54:49

标签: javascript leaflet ionic3

我正在使用Leaflet JS在地图上绘制多边形。

我能够绘制形状,并将形状保存为GeoJSON,如下所示:

.ts文件

...
    let layer = event.layer;
    let geometry = layer.toGeoJSON();
    this.drawLayer.addLayer(layer);
}

我在ngOnInit方法中调用一个方法来重绘形状:

drawPolygonShape(data) {
    if (data.polygon.geometry) {
        let shape = {
            type: data.polygon.type,
            geometry: {
                type: data.polygon.geometry.type,
                coordinates: data.polygon.geometry.coordinates
            },
            properties: {}
        };

        L.geoJSON(shape, {
            onEachFeature: this.onEachFeature
        }).addTo(this.myMap);
    }
}


...


onEachFeature(feature, layer) {
    layer.on('click', event => {
        // layer.bindPopup('Hello World'); // Works great
        let popover = this.popoverCtrl.create('MyComponent', { layer: layer });
        popover.present();
    });
}

我正在将MyComponent导入模块文件,因此我知道它可用。但是,我总是收到以下错误消息:

  

无法读取未定义的属性“创建”

因此,在某个地方存在计时或示波器问题,无法与click事件正确配合。

这似乎是一个范围问题,因为任何组件都会产生相同的错误。任何建议,不胜感激!

编辑

谢谢@ghybs,我尝试将this作为click事件的第三个参数,但是我仍然遇到相同的错误:

    onEachFeature(feature, layer) {
    layer.on('click', event => {
        // layer.bindPopup('Hello World'); // Works great
        let popover = this.popoverCtrl.create('MyComponent', { layer: layer });
        popover.present();
    }, this);
}

编辑2

谢谢@ghybs!

我很好奇您的第二个建议-我正在这样设置地图:

let mapOptions: any = {
    position: 'topright',
    draw: {
        polyline: false,
        ...
    }
}

...

let drawControl = new L.Control.Draw(mapOptions);
this.myMap.addControl(drawControl);

this.myMap.on(L.Draw.Event.CREATED, this.onCreatePolygon.bind(this));

.bind(this)现在更有意义了-onCreatePolygon是我用来保存形状的一种方法。

您如何建议我将每种形状委托给click事件?

this.myMap.on(L.Draw.Event.CLICK, this.MYCLICKHANDLER.bind(this));

(很明显,我对此并不熟悉,所以感谢您的所有时间。)

1 个答案:

答案 0 :(得分:1)

在您的情况下,您遇到了 double 上下文问题,因为您还传递了onEachFeature方法,该方法将使用与类实例已经不同的this上下文进行调用

您可以与onEachFeature: this.onEachFeature.bind(this)一起layer.on("click", cb, this)

您还可以通过将侦听器而不是每个单独的功能附加到GeoJSON图层组上来使用事​​件委托,这样您就可以摆脱其中的一种情况:

var geoJsonData = {
  "type": "Point",
  "coordinates": [2.35, 48.86]
};

class Component {
  constructor(mapId) {
    this.myMap = L.map(mapId).setView([48.86, 2.35], 11);

    L.geoJSON(geoJsonData).addTo(this.myMap).on("click", event => {
      console.log(event.target); // this is the GeoJSON Layer Group.
      console.log(event.layer); // this is the individual child feature.
      let popover = this.popoverCtrl.create('MyComponent');
      popover.present();
    }, this); // Not even needing the 3rd arg since you use a fat arrow function, which does not have its own context.

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.myMap);
  }
}

Component.prototype.popoverCtrl = { // Dummy popoverCtrl
  create(content) {
    dummyPopoverContent = content;
    return {
      present() {
        alert(dummyPopoverContent);
      },
    };
  },
};

var dummyPopoverContent = '';

new Component('map');
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>

<div id="map" style="height: 180px"></div>

另请参阅start a function when click on circle - leaflet


关于最后一个问题,使用上面的第一句话,您可以重写:

this.myMap.on(L.Draw.Event.CREATED, this.onCreatePolygon.bind(this));

进入:

this.myMap.on(L.Draw.Event.CREATED, this.onCreatePolygon, this);

在这种情况下,事件委托似乎无关紧要,因为您已经在地图上而非单个图层上附加了单个侦听器。