【问题标题】:How to center ngx-leaflet map inside ng-bootstrap modal如何在 ng-bootstrap 模态中居中 ngx-leaflet 地图
【发布时间】:2018-03-05 11:11:14
【问题描述】:

我想在一个 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)中,地图显示良好(居中)。

【问题讨论】:

    标签: angular leaflet twitter-bootstrap-4 ng-bootstrap ngx-leaflet


    【解决方案1】:

    传单对页面布局和大小的变化非常敏感。一般当页面布局发生变化时需要调用Map.invalidateSize()

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

    首先,使用 README 中的说明获取对 Map 的引用: 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 项目来重现该问题,我可以仔细查看。

    【讨论】:

    • 为了实现这一点,我需要在两个兄弟组件之间共享地图引用。使用服务实现这一目标的最佳方式是什么?
    • 我使用服务共享地图参考,但 invalidateSize() 调用不起作用。
    • 你能提供一个更完整的例子来重现这个问题吗?我可以检查并运行的东西?一个快速的测试是当你看到它看起来不工作时调整窗口大小,看看它是否修复它。调整窗口大小会强制内部调用 invalidateSize()
    【解决方案2】:

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

        /* // 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>
    

    【讨论】:

    猜你喜欢
    • 2018-04-04
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多