Как использовать 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".

  1. npm install azure-maps-control

Этот пакет включает в себя сокращенную версию исходного кода, а также определения TypeScript для веб-элемента управления Azure Maps.

  1. 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]
          }));
        });
      }
    
    }
    
  2. 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: ...
};
Другие вопросы по тегам