Как центрировать карту ngx-leaflet внутри модального ng-bootstrap
Я хочу отобразить карту ngx-leaflet внутри модального ng-bootstrap, центрированного в определенной точке. Карта инкапсулирована в такой компонент:
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">×</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) карта отображается нормально (по центру).
1 ответ
Листовка очень чувствительна к изменениям макета и размера страницы. Как правило, при изменении макета страницы вам нужно позвонить Map.invalidateSize()
,
Листовка ngx автоматически отслеживает события изменения размера окна и звонки invalidateSize()
для вас, так что вам обычно не нужно беспокоиться об этом. Но когда вы используете что-то вроде Bootstrap или JQuery для манипулирования макетом страницы независимо от изменения размера окна, вам может потребоваться вызвать его вручную.
Сначала возьмите ссылку на карту, используя инструкции в README: https://github.com/Asymmetrik/ngx-leaflet
<div leaflet
[leafletOptions]="options"
(leafletMapReady)="onMapReady($event)">
</div>
map: Map;
onMapReady(map: Map) {
this.map = map;
}
Затем добавьте вызов this.map.invalidateSize()
всякий раз, когда вы открываете / показываете / изменяете размеры модальной карты.
Если это не помогло, пожалуйста, предоставьте угловой проект CLI на GitHub, который воспроизводит проблему, и я могу взглянуть поближе.
Я Пархам, для решения этой проблемы в Angular 6 и начальной загрузке Modal используйте эту инструкцию. Сегодня исправил мою проблему с этой инструкцией. Чтобы исправить эту проблему, следует использовать методthis.map.invalidateSize();
в событии (листовка MouseOver). Пожалуйста, посмотрите этот пример кода отсюда.
/* // 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: '© <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>