2

我想在 ng-bootstrap 模态中显示一个 ngx-leaflet 地图,以一个确定的点为中心。该地图被封装在一个组件中,如下所示:

HTML

<div class="modal-header">
  <h4 class="modal-title">Map</h4>
  <button type="button" class="close" aria-label="Close" 
      (click)="activeModal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
  </button>
</div>

<div class="modal-body">
  <div id="map" 
    leaflet
    [leafletOptions]="options"
    [leafletLayersControl]="layersControl"></div>
</div>

<div class="modal-footer">
  <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>

TS

 constructor(public activeModal: NgbActiveModal) { }

  ngOnInit() {
  }

  streetMap = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
    maxZoom: 20,
    subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
  });

  hybridMap = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
    maxZoom: 20,
    subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
  });

  vehicleMarker = L.marker([40.4168, -3.703790], {
    icon: L.icon({
      iconSize: [25, 41],
      iconAnchor: [13, 41],
      iconUrl: 'assets/marker-icon.png',
      shadowUrl: 'assets/marker-shadow.png'
    })
  });

  layersControl = {
    baseLayers: {
      'Map view': this.streetMap,
      'Map hybrid': this.hybridMap
    },
    overlays: {
      'Vehicle': this.vehicleMarker
    }
  };

  options = {
    layers: [this.streetMap, this.vehicleMarker],
    zoom: 5,
    center: L.latLng([40.4168, -3.703790])
  };

在另一个组件中,我像这样打开模式:

constructor(private modalService: NgbModal) { }

ngOnInit() {
}

openMap() {
    this.modalService.open(MapComponent);
}

在模态之外一切正常(地图在给定点居中)但是当我在模态内渲染地图时,地图没有居中。我该如何解决这个问题?

我意识到在小屏幕(如 Galaxy S5 360x460)中,地图显示得很好(居中)。

4

2 回答 2

3

Leaflet 对页面布局和大小的更改非常敏感。通常,当页面布局发生变化时,您需要调用Map.invalidateSize().

ngx-leaflet 自动跟踪窗口调整大小事件并invalidateSize()为您调用,因此您通常不必担心它。但是,当您使用 Bootstrap 或 JQuery 之类的东西来独立于调整窗口大小来操作页面布局时,您可能需要手动调用它。

首先,使用自述文件中的说明获取对地图的引用: https ://github.com/Asymmetrik/ngx-leaflet#getting-a-reference-to-the-map

<div leaflet
     [leafletOptions]="options"
     (leafletMapReady)="onMapReady($event)">
</div>

map: Map;
onMapReady(map: Map) {
   this.map = map;
}

this.map.invalidateSize()然后,在您打开/显示/调整地图模式时添加一个调用。

如果这没有帮助,请在 GitHub 上提供一个 Angular CLI 项目来重现该问题,我可以仔细查看。

于 2018-03-05T14:47:34.840 回答
1

我是 Parham,为了解决 Angular 6 中的这个问题,并且 bootstrap Modal 使用这个指令。今天用这个指令解决了我的问题。要纠正这个问题,应该使用this.map.invalidateSize();事件中的方法(leafletMouseOver)。请从此处查看此示例代码。

    /* // In style.css add this class map */
.map {
  position: relative !important;
  width: 100%; height: 600px;
  margin: 2px;
  padding: 2px;
}

/*--------------------------------------------------------------------*/

// In Angular component .ts file

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import * as L from 'leaflet';

@Component({
  selector: 'app-map-control',
  template: 
    `<div class="map" leaflet
      (leafletMapReady)="onMapReady($event)"
      [leafletOptions]="options"
      (leafletMouseOver)="refreshMap()"
      style="border: black solid 1px;">
    </div>`
})

export class MapControlComponent {

  constructor() { }

  public map: L.Map = null;
  private latoLong: L.LatLngTuple = [35.706000, 51.4025000]; // for set static lat-long to map


  // Define our base layers so we can reference them multiple times
  streetMaps = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    detectRetina: true,
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  });

  // Set the initial set of displayed layers (we could also use the leafletLayers input binding for this)
  options = {
    layers: [this.streetMaps],
    zoom: 17,
    center: L.latLng(this.latoLong)
  };

  @Output() outputLatLong = new EventEmitter<L.LatLngTuple>();

  refreshMap() {
    if (this.map) {
      // this.streetMaps.redraw();
      this.map.invalidateSize();
    }
  }

  onMapReady(map: L.Map) {
    map.on('click', (eventMouse: L.LeafletMouseEvent) => {
      this.latoLong = [eventMouse.latlng.lat, eventMouse.latlng.lng];
      map.setView(this.latoLong, map.getZoom());
      this.outputLatLong.emit(this.latoLong);
    });
    this.map = map;
  }

}

在您的组件应用程序中使用:

<app-map-control (outputLatLong)="getLatLong($event)"></app-map-control>
于 2019-08-25T15:35:18.463 回答