#angular #google-maps
#angular #google-карты
Вопрос:
Следующий код взят из этой официальной документации и довольно хорошо работает в моем приложении Angular 10: https://developers.google.com/maps/documentation/javascript/marker-clustering?hl=en
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core'
import { Coordinates } from '@shared/models/coordinates.model';
import MarkerClusterer from '@googlemaps/markerclustererplus'
@Component({
selector: 'store-map',
template: `<div id="map" style="height: 500px"></div>`,
styleUrls: ['./store-map.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StoreMapComponent implements AfterViewInit {
@ViewChild('map', {static: false}) info: ElementRef;
ngAfterViewInit() {
const locations = [
{ lat: -31.56391, lng: 147.154312 },
{ lat: -33.718234, lng: 150.363181 },
{ lat: -33.727111, lng: 150.371124 },
{ lat: -33.848588, lng: 151.209834 },
{ lat: -33.851702, lng: 151.216968 },
{ lat: -34.671264, lng: 150.863657 },
{ lat: -35.304724, lng: 148.662905 },
{ lat: -36.817685, lng: 175.699196 },
{ lat: -36.828611, lng: 175.790222 },
{ lat: -37.75, lng: 145.116667 },
{ lat: -37.759859, lng: 145.128708 },
{ lat: -37.765015, lng: 145.133858 },
{ lat: -37.770104, lng: 145.143299 },
{ lat: -37.7737, lng: 145.145187 },
{ lat: -37.774785, lng: 145.137978 },
{ lat: -37.819616, lng: 144.968119 },
{ lat: -38.330766, lng: 144.695692 },
{ lat: -39.927193, lng: 175.053218 },
{ lat: -41.330162, lng: 174.865694 },
{ lat: -42.734358, lng: 147.439506 },
{ lat: -42.734358, lng: 147.501315 },
{ lat: -42.735258, lng: 147.438 },
{ lat: -43.999792, lng: 170.463352 },
];
const map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
zoom: 3,
center: { lat: -28.024, lng: 140.887 },
}
)
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const markers = locations.map((location, i) => {
return new google.maps.Marker({
position: location,
label: labels[i % labels.length],
});
});
new MarkerClusterer(map, markers, {
imagePath:
"https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m",
});
}
}
Кластеризация маркеров здесь работает хорошо. К сожалению, на самом деле это не «угловой способ» для достижения того, чего я хочу. Что я хочу, так это использовать «новый» собственный компонент Google Maps из Angular. Итак, вот что я сделал (без кластеризации маркеров):
Компонент:
@Component({
selector: 'store-map',
templateUrl: './store-map.component.html',
styleUrls: ['./store-map.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StoreMapComponent {
@Input()
coordinates: Coordinates
@Input()
zoom: number
@Input()
set stores(value: Store[]) {
// Allow time for the map to load before showing markers
if (this.isFirstLoad amp;amp; value.length > 0) {
this.isFirstLoad = false
setTimeout(() => {
this._stores = value
this.changeDetector.markForCheck() // Needed because of setTimeout()
}, 1000)
} else {
this._stores = value
}
}
private isFirstLoad = true
_stores: Store[] = []
markerOptions: google.maps.MarkerOptions = {
animation: Animation.DROP,
icon: {
url: '/assets/img/yarn.png',
size: new google.maps.Size(32, 32)
}
}
constructor(private changeDetector: ChangeDetectorRef) { }
getStoreLatLngLiteral(store: Store): google.maps.LatLngLiteral {
return this.mapCoordinatesToLatLngLiteral({
latitude: store.lat,
longitude: store.lng
})
}
mapCoordinatesToLatLngLiteral(coordinates: Coordinates): google.maps.LatLngLiteral {
return {
lat: coordinates.latitude,
lng: coordinates.longitude
}
}
Шаблон:
<google-map [center]="mapCoordinatesToLatLngLiteral(coordinates)" [zoom]="zoom" width="auto">
<map-marker *ngFor="let store of _stores" [position]="getStoreLatLngLiteral(store)"
[title]="store.name"
[options]="markerOptions">
</map-marker>
</google-map>
Проблема в том, что на данный момент я не знаю, как настроить кластеризацию маркеров «угловым способом».
Ответ №1:
Если вы хотите использовать официальную документацию, вы можете просто загрузить JS-скрипт непосредственно на index.html файл, вместо того, чтобы полагаться на сторонние модули / пакеты, которые имеют свою собственную документацию.
Вот пример для справки: https://stackblitz.com/edit/angular-marker-cluster-64960574
index.html
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
<script src="https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script>
<my-app>loading</my-app>
style.css
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.map {
height:100%;
}
map-with-marker.component.html
<div #map class="map"></div>
map-with-marker.component.ts
import { Component, OnInit, ViewChild } from "@angular/core";
declare const google: any;
@Component({
selector: "my-maps",
templateUrl: "./map-with-marker.component.html",
styleUrls: ["./map-with-marker.component.css"]
})
export class MapComponent implements OnInit {
@ViewChild("map", { static: true }) mapElement: any;
map: any;
constructor() {}
ngOnInit() {
const locations = [
{ lat: -31.56391, lng: 147.154312 },
{ lat: -33.718234, lng: 150.363181 },
{ lat: -33.727111, lng: 150.371124 },
{ lat: -33.848588, lng: 151.209834 },
{ lat: -33.851702, lng: 151.216968 },
{ lat: -34.671264, lng: 150.863657 },
{ lat: -35.304724, lng: 148.662905 },
{ lat: -36.817685, lng: 175.699196 },
{ lat: -36.828611, lng: 175.790222 },
{ lat: -37.75, lng: 145.116667 },
{ lat: -37.759859, lng: 145.128708 },
{ lat: -37.765015, lng: 145.133858 },
{ lat: -37.770104, lng: 145.143299 },
{ lat: -37.7737, lng: 145.145187 },
{ lat: -37.774785, lng: 145.137978 },
{ lat: -37.819616, lng: 144.968119 },
{ lat: -38.330766, lng: 144.695692 },
{ lat: -39.927193, lng: 175.053218 },
{ lat: -41.330162, lng: 174.865694 },
{ lat: -42.734358, lng: 147.439506 },
{ lat: -42.734358, lng: 147.501315 },
{ lat: -42.735258, lng: 147.438 },
{ lat: -43.999792, lng: 170.463352 }
];
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var center = { lat: -33.8569, lng: 151.2152 };
const mapProperties = {
center: center,
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(
this.mapElement.nativeElement,
mapProperties
);
this.addMarker(locations, labels);
}
addMarker(locations, labels) {
const markers = locations.map((location, i) => {
return new google.maps.Marker({
position: location,
label: labels[i % labels.length],
map: this.map
});
});
new MarkerClusterer(this.map, markers, {
imagePath:
"https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m"
});
}
}
Если вы столкнулись
google is not defined
, просто поставьте пробел в любой части кода (например, в файле .ts), поскольку у Stackblitz, похоже, есть проблема.
Комментарии:
1. Как я уже говорил в своем первоначальном посте, кластеризация маркеров хорошо работает, когда я использую JS-скрипты напрямую. Но я хотел бы сделать это «угловым способом», используя компонент и директивы Angular.
Ответ №2:
С помощью пакета Google Maps от Angular ( @angular/google-maps
) вы можете использовать кластеры маркеров аналогично приведенному выше примеру;
component.ts
import {Component} from '@angular/core';
@Component({
selector: 'google-map-demo',
templateUrl: 'google-map-demo.html',
})
export class GoogleMapDemo {
center: google.maps.LatLngLiteral = {lat: 24, lng: 12};
zoom = 4;
markerPositions: google.maps.LatLngLiteral[] = [];
markerClustererImagePath =
'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m';
addMarker(event: google.maps.MouseEvent) {
this.markerPositions.push(event.latLng.toJSON());
}
}
component.html
<google-map height="400px"
width="750px"
[center]="center"
[zoom]="zoom"
(mapClick)="addMarker($event)">
<map-marker-clusterer [imagePath]="markerClustererImagePath">
<map-marker *ngFor="let markerPosition of markerPositions"
[position]="markerPosition"></map-marker>
</map-marker-clusterer>
</google-map>
Полная ссылка на их документацию и как загрузить библиотеку здесь
Это будет доступно в версии 11.1.0 (как здесь) или вы можете загрузить сборку сейчас.
Комментарии:
1. Можно ли что-нибудь сделать, чтобы заставить это работать, например, импортировать модуль или что-то в этом роде? Потому что Angular говорит мне об этом
'map-marker-clusterer' is not a known element
. Я использую@angular/google-maps@10.2.7
2. @Flobesst Вы перешли по ссылке, о которой я упоминал выше, о загрузке библиотеки через
<script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>
as, как она предлагает? Или через@googlemaps/markerclustererplus
3. Да, я добавил скрипт в свой
index.html
, и у меня все еще есть то же сообщение об ошибке.4. Похоже, что его еще предстоит развернуть как часть пакета Angular в версии 11.1.0. Обновленный ответ с соответствующими ссылками и загрузкой.
5. О, хорошо, поэтому мне придется обновить Angular до последней версии. Я дам вам знать.