2

我遇到了一个问题,其他人似乎都遇到了我的 ngx-leaflet 地图在我调整大小之前没有完全呈现的问题。我尝试以多种方式调用 map.invalidateSize(),例如在 ngOnInit、onMapReady 中,所有上述方法都带有超时。我在初始加载时得到了这个。我正在使用 ngx-leaflet 2.5,因为 3.0+ 不适用于 angular 4.4.5。

访问模式的按钮是

<app-map
  (closeButtonClicked)="mapModal.hide()"
  class="modal fade"
  bsModal
  #mapModal="bs-modal"
  tabindex="-1"
  role="dialog"
  aria-labelledby="mySmallModalLabel"
  aria-hidden="true"
  [Service]="Service"></app-map>

CSS是:

@import '../../app';
#map {
  color: white;
  font: 1em 'Dosis', Arial, sans-serif;
  width: 90vh;
  margin: 30px auto;
  button.close {
    font-size: 30px;
    opacity: .4;
  }
  .modal-dialog {
    width: 100vw;
    height: 50vw;
    .devices-sm({
      width: 90vh;
      height: 70vh;
    });
    .modal-content {
      height: 100%;
      .modal-body {
        height: 100%;
        background-color: @accent-background-color;
        padding: 0;
        #map {
          height: 100%;
          width: 100%;
          padding: 0;
        }
      }
    }
  }
}

这是实际地图的代码

googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
    maxZoom: 20,
    subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
    detectRetina: true
});
options = {
    layers: [
        this.googleHybrid
    ],
    zoom: 1.49,
    center: L.latLng([180, -180]),

};
4

2 回答 2

2

Leaflet 对地图的大小非常敏感。这意味着无论何时显示/隐藏地图,都需要确保调用该invalidateSize()方法。使用 ngx-bootstrap 模式,正确的时间将在onShown事件处理程序中。

我创建了 ngx-leaflet-tutorial-ngcli GitHub 项目 [1] 的一个分支,它展示了如何让它工作。虽然此示例适用于 ng5 和 ngx-leaflet@3,但同样的方法也适用于 ng4 和 ngx-leaflet@2。

[1] https://github.com/Asymmetrik/ngx-leaflet-tutorial-ngcli/compare/develop...ngx-bootstrap-modal-demo

相关摘录如下。

在您的组件中,为 onShown 事件添加一个处理程序:

handleOnShown() {
   this.map.invalidateSize();
}

在您的模板中,设置 (onShown) 输出以调用处理程序:

<button type="button" class="btn btn-primary"
        (click)="staticModal.show()">
  Show a Map
</button>

<div class="modal fade"
     bsModal #staticModal="bs-modal"
     [config]="{backdrop: 'static'}"
     tabindex="-1" role="dialog"
     aria-labelledby="mySmallModalLabel" aria-hidden="true"
     (onShown)="handleOnShown()">

  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title pull-left">Static modal</h4>
        <button type="button" class="close pull-right"
                aria-label="Close"
                (click)="staticModal.hide()">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <div class="map"
             leaflet
             (leafletMapReady)="onMapReady($event)"
             [leafletOptions]="options"
             [leafletLayersControl]="layersControl"></div>
      </div>
    </div>
  </div>
</div>
于 2018-03-27T02:43:58.450 回答
1
/* // 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;
  }

}
于 2019-08-25T15:22:59.633 回答