Как использовать Azure Maps в Angular
Я не могу найти поддержку, модуль или документацию для использования карт Azure в Angular. Карты Azure все еще слишком новы и еще не поддерживают Angular?
Я пробовал следующий модуль без успеха: https://www.npmjs.com/package/angular-azure-maps
Я пытался следовать инструкциям Microsoft в своих документах для карт Azure (не-Angular), но безуспешно.
Я использую Angular версии 5.2.9.
6 ответов
Карты Azure довольно новы, и у нас еще не было возможности заглянуть в Angular (я менеджер программ для элементов управления картами на картах Azure). Здесь есть проект с открытым исходным кодом, который был запущен сообществом: https://github.com/Acaisoft/angular-azure-maps Я полагаю, что это исходный код библиотеки, которую вы пробуете на npm.
Мы планируем изучить вопрос о том, как сделать использование Azure Maps проще в Angular в новом году, но, скорее всего, начнем с интеграции его в одну из многих существующих библиотек Angular.
Я рекомендую сделать запрос о функции, чтобы мы могли отследить это, а другие могут сообщить об этом здесь: https://feedback.azure.com/forums/909172-azure-maps
Карты Azure с Angular легко использовать.
Во-первых, вам нужно установить пакет npm: npm i azure-maps-control --save
.
Затем измените свой angular.json
файл. Включить файлы вstyles
а также scripts
:
"styles": [
"node_modules/azure-maps-control/dist/atlas.min.css",
"src/styles.scss"
],
"scripts": [
"node_modules/azure-maps-control/dist/atlas.min.js"
]
После этого в вашем компоненте создайте ViewChild
для вас контейнер карты и инициализировать карту. Не забудьте указать ключ подписки Azure Maps из переменной среды.
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { Map, AuthenticationType } from 'azure-maps-control';
import { environment } from '@environments/environment';
@Component({
selector: 'app-map-component',
templateUrl: './map.component.html',
styleUrls: [ './map.component.scss' ]
})
export class MapComponent implemens AfterViewInit {
@ViewChild('map', { static: true })
public mapContainer: ElementRef;
public ngAfterViewInit(): void {
const map = new Map(this.mapContainer.nativeElement, {
center: [50.016, 36.13],
zoom: 8,
authOptions: {
authType: AuthenticationType.subscriptionKey,
subscriptionKey: environment.azureMapsSubscriptionKey
}
});
}
}
И вот твой map.component.html
<div #map></div>
Я думаю, что лучше всего использовать родной контроль над Azure-картами. И демонстрационные примеры из Azure Maps Web Control Samples.
Протестировано с @angular: "^7.2.4".
npm install azure-maps-control
Этот пакет включает в себя сокращенную версию исходного кода, а также определения TypeScript для веб-элемента управления Azure Maps.
maps.component.ts
import { Component, OnInit } from '@angular/core'; import * as atlas from 'azure-maps-control'; @Component({ selector: 'app-maps', templateUrl: './maps.component.html', styleUrls: ['./maps.component.scss'] }) export class MapsComponent implements OnInit { // Azure Active Directory Authentication Client ID // or Shared Key Authentication KEY // get it from portal.azure.com key: string = '{key}'; map: any; constructor( ) { } ngOnInit() { //Initialize a map instance. this.map = new atlas.Map('mapContainer', { authOptions: { authType: 'subscriptionKey', subscriptionKey: this.key } }); //Wait until the map resources are ready. this.map.events.add('ready', () => { //Create a HTML marker and add it to the map. this.map.markers.add(new atlas.HtmlMarker({ color: 'DodgerBlue', text: '10', position: [0, 0] })); }); } }
maps.component.html
<div id="mapContainer"></div>
В дополнение к ответу @rbrundritt я пробовал библиотеку Acaisoft Azure Maps, и она полна ошибок, и ни один из примеров, связанных с этим репозиторием GitHub, не работает вообще... Но, думаю, у меня есть хорошие новости, "Крис Пендлтон","Главный менеджер по управлению проектами Azure Maps", рассказывает об уровне цен S1, и я обнаружил, что
... мы также объединили определения TypeScript с копией исходного кода Azure Maps Web SDK и сделали его доступным в качестве пакета NPM, упрощая тем самым интеграцию с современными веб-платформами и предоставляя возможность размещения карт Azure. Web SDK локально с вашим приложением для быстрой загрузки. Вы можете найти Azure-Maps-Control или установить его из командной строки, используя следующее:
Npm и Azure-карты-контроль
РЕДАКТИРОВАТЬ (несколько часов спустя):
Я безуспешно пробовал библиотеку, и в то же время команды Azure Maps создают надлежащую документацию и, надеюсь, руководство по выполнению этой работы под углом, я буду продолжать использовать Leaflet и MapBox.
Я надеюсь, что это помогает.
Ответы @Vlad и @Alexey очень полезны, но я хотел бы предоставить дополнительный пример для всех, кто хочет использовать код из библиотеки образцов, особенно тех образцов, которые требуют услуг. Ниже представлена версия модуля Fuzzy Search with Services с минимальными настройками, необходимыми для использования в Angular.
import { Component, ViewChild, ElementRef, AfterViewInit } from "@angular/core";
import * as atlas from 'azure-maps-control';
import * as atlasRest from 'azure-maps-rest'; // install npm azure-maps-rest
@Component({
selector: 'map',
templateUrl: './map.component.html',
styles: ['#map {height: 300px; width: 1110px;}']
//Remember to set the dimensions of the map container or layers may appear
//offset or behind the map.
})
export class MapComponent implements AfterViewInit {
@ViewChild('input') public input: ElementRef;
@ViewChild('mapContainer') public mapContainer: ElementRef;
private key: string = '<Your Azure Maps Key>';
public map: any;
public dataSource: any;
public popup: any;
public searchURL: any;
ngAfterViewInit(): void {
this.map = new atlas.Map(this.mapContainer.nativeElement, {
view: 'Auto',
authOptions: {
authType: atlas.AuthenticationType.subscriptionKey,
subscriptionKey: this.key
}
});
//Create a pipeline using the Azure Maps subscription key.
var pipeline = atlasRest.MapsURL.newPipeline(new atlasRest.SubscriptionKeyCredential(atlas.getSubscriptionKey()));
//Create an instance of the SearchURL client.
this.searchURL = new atlasRest.SearchURL(pipeline);
//Wait until the map resources are ready.
this.map.events.add('ready', () => {
// Add zoom control
this.map.controls.add(new atlas.control.ZoomControl(), {
position: 'bottom-left'
});
//Create a data source and add it to the map.
this.dataSource = new atlas.source.DataSource();
this.map.sources.add(this.dataSource);
//Add a layer for rendering the results as symbols.
var resultsLayer = new atlas.layer.SymbolLayer(this.dataSource);
this.map.layers.add(resultsLayer);
//Create a popup but leave it closed so we can update it and display it later.
this.popup = new atlas.Popup({
position: [0, 0],
pixelOffset: [0, -18]
});
//Add a click event to the results symbol layer.
//Remember to bind the event to 'this' or the this.popup and this.map
//lines of the symbolClicked function will return undefined!
this.map.events.add('click', resultsLayer, this.symbolClicked.bind(this));
});
}
public closePopup(): void {
this.popup.close();
}
public search(): void {
var query = this.input.nativeElement.value;
//Remove any previous results from the map.
this.dataSource.clear();
this.searchURL.searchFuzzy(atlasRest.Aborter.timeout(10000), query, {
radius: 100000,
view: 'Auto'
}).then(results => {
//Get the results in GeoJSON format and add it to the data source.
var data = results.geojson.getFeatures();
this.dataSource.add(data);
//Set the camera to the bounds of the results.
this.map.setCamera({
bounds: data.bbox,
padding: 40
});
});
}
public symbolClicked(e): void {
//Make sure the event occurred on a point feature.
if (e.shapes && e.shapes.length > 0 && e.shapes[0].getType() === 'Point') {
var properties = e.shapes[0].getProperties();
//Using the properties, create HTML to fill the popup with useful information.
var html = ['<div style="padding:10px;"><span style="font-size:14px;font-weight:bold;">'];
var addressInTitle = false;
if (properties.type === 'POI' && properties.poi && properties.poi.name) {
html.push(properties.poi.name);
} else if (properties.address && properties.address.freeformAddress) {
html.push(properties.address.freeformAddress);
addressInTitle = true;
}
html.push('</span><br/>');
if (!addressInTitle && properties.address && properties.address.freeformAddress) {
html.push(properties.address.freeformAddress, '<br/>');
}
html.push('<b>Type: </b>', properties.type, '<br/>');
if (properties.entityType) {
html.push('<b>Entity Type: </b>', properties.entityType, '<br/>');
}
if (properties.type === 'POI' && properties.poi) {
if (properties.poi.phone) {
html.push('<b>Phone: </b>', properties.poi.phone, '<br/>');
}
if (properties.poi.url) {
html.push('<b>URL: </b>', properties.poi.url, '<br/>');
}
if (properties.poi.classifications) {
html.push('<b>Classifications:</b><br/>');
for (var i = 0; i < properties.poi.classifications.length; i++) {
for (var j = 0; j < properties.poi.classifications[i].names.length; j++) {
html.push(' - ', properties.poi.classifications[i].names[j].name, '<br/>');
}
}
}
}
html.push('</div>');
//Set the popup options.
this.popup.setOptions({
//Update the content of the popup.
content: html.join(''),
//Update the position of the popup with the pins coordinate.
position: e.shapes[0].getCoordinates()
});
//Open the popup.
this.popup.open(this.map);
}
}
}
Тогда html будет примерно таким:
<input type="search" #input>
<button (click)="search()">Search</button>
<div #mapContainer id="map"></div>
(Примечание: этот пример предназначен как можно ближе к образцу кода, чтобы упростить сравнение, но его можно улучшить с помощью соглашений Angular и TypeScript).
Вот как я получил карты Azure для работы со спутником.
Я импортировал листовку в app.module (просто импортировал, не нужно ничего добавлять в массив импорта).
import 'leaflet';
В компоненте, в котором я создаю карту, я создал спутниковый слой следующим образом:
const azureMapsUrl = `https://atlas.microsoft.com/map/imagery/png?api-version=1&style=satellite&tileSize=512&zoom={z}&x={x}&y={y}&subscription-key=${myAzureMapsKey}`;
this.satelliteLayer = new L.TileLayer(azureMapsUrl);
Затем я добавил слой к своим параметрам листовки:
this.leafletOptions = {
zoomControl: false,
minZoom: 6,
layers: [this.satelliteLayer],
zoom: 6,
center: ...
};