简体   繁体   English

如何在 Angular 中使用 Azure Maps

[英]How to use Azure Maps in Angular

I cannot find any support, module or documentation for using Azure Maps in Angular.我找不到在 Angular 中使用 Azure Maps 的任何支持、模块或文档。 Is Azure Maps still too new and have no support for Angular yet? Azure Maps 还是太新并且还不支持 Angular 吗?

I have tried the following module without success: https://www.npmjs.com/package/angular-azure-maps我尝试了以下模块但没有成功: https : //www.npmjs.com/package/angular-azure-maps

I have tried following Microsofts instructions in their documentations for Azure Maps (non-Angular), but without success.我曾尝试按照 Microsoft 在 Azure Maps(非 Angular)文档中的说明进行操作,但没有成功。

I am using Angular version 5.2.9.我正在使用 Angular 版本 5.2.9。

Azure Maps is fairly new and we haven't had a chance to look into Angular ourselves yet (I'm the program manager for map controls on Azure Maps). Azure Maps 是相当新的,我们自己还没有机会研究 Angular(我是 Azure Maps 地图控件的项目经理)。 There is an open source project that has been started by the community here: https://github.com/Acaisoft/angular-azure-maps I believe this is the source code to the library you are trying on npm.社区在这里启动了一个开源项目: https : //github.com/Acaisoft/angular-azure-maps我相信这是您在 npm 上尝试的库的源代码。

We do plan to investigate how we can make using Azure Maps easier to use in Angular in the new year, but will likely start by integrating it into one of the many existing Angular map libraries that exist.我们确实计划研究如何在新的一年中让 Azure Maps 在 Angular 中更易于使用,但可能会首先将其集成到现有的众多 Angular 地图库之一中。

I recommend make a feature request so we can track this and others can upvote it here: https://feedback.azure.com/forums/909172-azure-maps我建议提出功能请求,以便我们可以跟踪此内容,其他人可以在此处对其进行投票: https ://feedback.azure.com/forums/909172-azure-maps

It's easy to use Azure Maps with Angular.将 Azure Maps 与 Angular 结合使用很容易。

Firstly, you need to install npm package: npm i azure-maps-control --save .首先,您需要安装 npm 包: npm i azure-maps-control --save

Then, modify your angular.json file.然后,修改您的angular.json文件。 Include files to the styles and scripts :将文件包含到stylesscripts

"styles": [
    "node_modules/azure-maps-control/dist/atlas.min.css",
    "src/styles.scss"
],
"scripts": [
    "node_modules/azure-maps-control/dist/atlas.min.js"
]

After that in your component, create ViewChild for you map container and initialize map.之后,在您的组件中,为您的地图容器创建ViewChild并初始化地图。 Don't forget to include some Azure Maps Subscription Key from the environment variable.不要忘记在环境变量中包含一些 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
            }
        });
    }
}

And here's your map.component.html这是你的map.component.html

<div #map></div>

I think that best way is to use native azure-maps-control .我认为最好的方法是使用本机azure-maps-control And demos from Azure Maps Web Control Samples .以及来自Azure Maps Web Control Samples 的演示。

Tested with @angular: "^7.2.4".用@angular 测试:“^7.2.4”。

  1. npm install azure-maps-control

This package includes a minified version of the source code as well as the TypeScript definitions for the Azure Maps Web Control.此包包括源代码的缩小版本以及 Azure Maps Web 控件的 TypeScript 定义。

  1. maps.component.ts地图.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地图.component.html

     <div id="mapContainer"></div>

In addition to @rbrundritt answer, I've been trying Acaisoft Azure Maps library and, well, it is full of errors and none of the samples linked from that GitHub repository work at all... But I guess I have good news, there is a Post, by Chris Pendleton,"Principal PM Manager, Azure Maps" , talking about S1 pricing tier and there I've found that除了@rbrundritt 的回答,我一直在尝试 Acaisoft Azure Maps 库,而且它充满了错误,而且从那个 GitHub 存储库链接的样本根本没有工作......但我想我有好消息,那里是Chris Pendleton 的帖子,“Azure Maps 首席 PM 经理” ,谈论 S1 定价层,我发现

... we have also combined the TypeScript definitions with a copy of the Azure Maps Web SDK source code and made it available as a NPM package, thus making it easier to integrate with modern web frameworks and providing you the option to host the Azure Maps Web SDK locally with your app for faster loading. ...我们还将 TypeScript 定义与 Azure Maps Web SDK 源代码的副本相结合,并将其作为 NPM 包提供,从而更轻松地与现代 Web 框架集成,并为您提供托管 Azure Maps 的选项Web SDK 与您的应用程序在本地连接以加快加载速度。 You can find Azure-Maps-Control or install it from the command line using the following:您可以找到Azure-Maps-Control或使用以下命令从命令行安装它:

npm i azure-maps-control npm i azure-maps-control

EDIT (few hours later):编辑(几个小时后):

I tried the library without success and meanwhile Azure Maps teams creates proper documentation and hopefully a how-to guide to make that work in angular I'll keep using Leaflet and MapBox.我尝试了这个库但没有成功,同时 Azure Maps 团队创建了适当的文档,并希望有一个如何在 angular 中工作的指南,我将继续使用 Leaflet 和 MapBox。

I hope it helps.我希望它有帮助。

@Vlad's and @Alexey's answers are very helpful but I'd like to provide an additional example for anyone wanting to use code from the sample library , especially those samples which require services. @Vlad 和 @Alexey 的回答非常有帮助,但我想为任何想要使用示例库中的代码的人提供一个额外的示例,尤其是那些需要服务的示例。 Below is a version of the Fuzzy Search with Services Module with the minimum adjustments necessary for use in Angular.下面是带有服务模块模糊搜索的一个版本,其中包含在 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);
        }
    }
}

The html would then be something like: html 将类似于:

<input type="search" #input>
<button (click)="search()">Search</button>

<div #mapContainer id="map"></div>

(Note: This example is intended to be as close to the sample code as possible to make comparison simpler but could be improved using Angular and TypeScript conventions). (注意:此示例旨在尽可能接近示例代码以使比较更简单,但可以使用 Angular 和 TypeScript 约定进行改进)。

This is how I got Azure maps to work for sattelite view.这就是我让 Azure 地图用于卫星视图的方式。

I imported leaflet in the app.module (simply imported, no need to add anything to imports array).我在 app.module 中导入了传单(只需导入,无需在导入数组中添加任何内容)。

import 'leaflet';

In the component where I am generating a map, I created the satellite layer like this:在我生成地图的组件中,我创建了卫星图层,如下所示:

const azureMapsUrl = `https://atlas.microsoft.com/map/imagery/png?api-version=1&style=satellite&zoom={z}&x={x}&y={y}&subscription-key=${myAzureMapsKey}`;
this.satelliteLayer = new L.TileLayer(azureMapsUrl);

I then added the layer to my leaflet options:然后我将图层添加到我的传单选项中:

this.leafletOptions = {
        zoomControl: false,
        minZoom: 6,
        layers: [this.satelliteLayer],
        zoom: 6,
        center: ...
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM