首页 > 解决方案 > 基于 Bootstrap 选择输入更新 ngx-leaflet 映射

问题描述

我有一个应用程序,当您基于此示例在 ngx-leaflet 中单击地图上的多边形时,它会更新 Bootstrap 选择输入下拉菜单。我还希望能够从选择输入中选择一个多边形名称,并具有与单击事件相同的功能——在这种情况下,fitBounds用于平移和缩放到选定的多边形。

我在我的 HTML 模板中添加了事件绑定,该模板会检测下拉菜单中的每个新选择。onChange()我向那个事件传递了一个新函数。但我很难过从这里去哪里。在点击事件中,我可以e.target用来访问所选多边形的边界。但在里面onChange(),我只能访问所选多边形的名称,但实际上我并没有与该多边形相关联的几何图形。那么如何使用下拉选择输入来选择多边形名称并让地图更新与该名称关联的多边形?(请注意,我希望得到灵活的响应,因为我想做的不仅仅是fitBounds()在这个示例之外的实际应用程序中。)

这是我的示例代码:

polygons.geojson(在assets文件夹中)

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "name": "poly1"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -121.95098876953125,
              46.82966386051541
            ],
            [
              -121.78482055664061,
              46.82966386051541
            ],
            [
              -121.78482055664061,
              46.91368905872705
            ],
            [
              -121.95098876953125,
              46.91368905872705
            ],
            [
              -121.95098876953125,
              46.82966386051541
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "name": "poly2"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -121.77726745605469,
              46.83107318799318
            ],
            [
              -121.62963867187499,
              46.83107318799318
            ],
            [
              -121.62963867187499,
              46.913220009605624
            ],
            [
              -121.77726745605469,
              46.913220009605624
            ],
            [
              -121.77726745605469,
              46.83107318799318
            ]
          ]
        ]
      }
    }
  ]
}

app.component.html

<div class="map"
  leaflet
  [leafletLayers]="layers"
     [leafletFitBounds]="fitBounds"></div>
<div class="form-group">
  <select [(ngModel)]="selected" class="form-control" id="selectRegion" [value]="clicked" (change)="onChange()">
    <option *ngFor="let region of regions">{{ region }}</option>
  </select>
</div>

app.component.ts

import {Component, NgZone, OnInit} from '@angular/core';
import { HttpClient } from '@angular/common/http';

import * as L from 'leaflet';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  layers: L.Layer[];
  fitBounds = [[46.67, -122.25], [47.01, -121.302]];
  regions = [];
  clicked = '';
  selected = '';

  constructor(private http: HttpClient, private zone: NgZone) { }

  ngOnInit() {

    // read in geojson of poly
    this.http.get<any>('/assets/polygons.geojson')
      .subscribe(poly => {

        const tileLayer = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png', {
          subdomains: 'abcd',
          maxZoom: 19
        });

        const polyLayer = L.geoJSON(poly, {
          onEachFeature: this.onEachFeature.bind(this)
        });

        this.layers = [ tileLayer, polyLayer ];
      });
  }

  // loop through each feature of polyLayer
  onEachFeature(feature, layer) {
    this.zone.run(() => {
      // push polygon names to regions array
      this.regions.push(feature.properties.name);

      layer.on('click', <LeafletMouseEvent> (e) => {
        this.zone.run(() => {
          this.fitBounds = e.target.getBounds();
          this.clicked = e.target.feature.properties.name;
        });
      });
    });
  }

  onChange() {
    console.log(this.selected);
  }
}

标签: angulardrop-down-menuleafletbootstrap-selectngx-leaflet

解决方案


我能够通过首先polyLayer在我的 App Component 类的顶部初始化为 null 属性来解决这个问题constructor()。因此,我在其余代码中更新了polyLayerto的实例。this.polyLayer有了这个,我现在可以访问里面的多边形onChange(),用 过滤eachLayer(),并适应地图的边界:

app.component.ts 更新

import {Component, NgZone, OnInit} from '@angular/core';
import { HttpClient } from '@angular/common/http';

import * as L from 'leaflet';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  layers: L.Layer[];
  fitBounds = [[46.67, -122.25], [47.01, -121.302]];
  regions = [];
  clicked = '';
  selected = '';
  polyLayer = null;

  constructor(private http: HttpClient, private zone: NgZone) { }

  ngOnInit() {

    // read in geojson of poly
    this.http.get<any>('/assets/polygons.geojson')
      .subscribe(poly => {

        const tileLayer = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png', {
          subdomains: 'abcd',
          maxZoom: 19
        });

        this.polyLayer = L.geoJSON(poly, {
          onEachFeature: this.onEachFeature.bind(this)
        });

        this.layers = [ tileLayer, this.polyLayer ];
      });
  }

  // loop through each feature of polyLayer
  onEachFeature(feature, layer) {
    this.zone.run(() => {
      // push polygon names to regions array
      this.regions.push(feature.properties.name);

      layer.on('click', <LeafletMouseEvent> (e) => {
        this.zone.run(() => {
          this.fitBounds = e.target.getBounds();
          this.clicked = e.target.feature.properties.name;
        });
      });
    });
  }

  onChange() {

    let that = this;

    // console.log(this.polyLayer._layers);
    this.polyLayer.eachLayer(function(layer){
      if(layer.feature.properties.name === that.selected){
        that.fitBounds = layer.getBounds();
      }
    });
  }
}

推荐阅读