在地图上显示兴趣点

重要

必应地图企业版服务停用

Windows.Services.Maps 命名空间中的 UWP MapControl 和地图服务依赖于必应地图。 必应地图企业版已弃用,并且将停用,此时 MapControl 和服务将不再接收数据。

有关详细信息,请参阅必应地图开发人员中心和必应地图文档

注意

MapControl 和地图服务需要称为 MapServiceToken 的地图身份验证密钥。 有关获取和设置地图身份验证密钥的详细信息,请参阅请求地图身份验证密钥

使用图钉、图像、形状和 XAML UI 元素向地图添加兴趣点(POI)。 POI 是地图上的一个特定点,表示感兴趣的内容。 例如,企业、城市或朋友的位置。

通过将 MapIconMapBillboardMapPolygonMapPolyline 对象添加到 MapElementsLayer 对象的 MapElements 集合,在地图上显示图钉、图像和图形。 然后,将该层对象添加到 地图控件的 Layers 集合中。

注意

在以前的版本中,本指南介绍了如何将地图元素添加到 MapElements 集合。 虽然仍然可以使用此方法,但会错过新地图层模型的某些优势。 若要了解详细信息,请参阅本指南的“ 使用层 ”部分。

还可以通过将 XAML 用户界面元素(如 ButtonHyperlinkButton 或 TextBlock)添加到 MapItemsControl 或 MapControl 级来在地图上显示它们。

如果地图上放置了大量元素,请考虑 在地图上覆盖平铺图像。 若要在地图上显示道路,请参阅显示路线和方向

添加图钉

使用 MapIcon 类在地图上显示具有可选文本的图钉图像。 可以使用 Image 属性接受默认映像或提供自定义映像。 下图显示 MapIcon 的默认图像,其中没有为 Title 属性指定值、具有短标题、具有长标题和很长标题。

具有不同长度的标题的示例 mapicon。

下面的示例演示西雅图市的地图,并添加一个 具有默认图像和可选标题的 MapIcon ,以指示 Space Needle 的位置。 它还将地图居中位于图标上并放大。 有关使用地图控件的一般信息,请参阅 显示具有 2D、3D 和街景视图的地图。

public void AddSpaceNeedleIcon()
{
    var MyLandmarks = new List<MapElement>();

    BasicGeoposition snPosition = new BasicGeoposition { Latitude = 47.620, Longitude = -122.349 };
    Geopoint snPoint = new Geopoint(snPosition);

    var spaceNeedleIcon = new MapIcon
    {
        Location = snPoint,
        NormalizedAnchorPoint = new Point(0.5, 1.0),
        ZIndex = 0,
        Title = "Space Needle"
    };

    MyLandmarks.Add(spaceNeedleIcon);

    var LandmarksLayer = new MapElementsLayer
    {
        ZIndex = 1,
        MapElements = MyLandmarks
    };

    myMap.Layers.Add(LandmarksLayer);

    myMap.Center = snPoint;
    myMap.ZoomLevel = 14;

}

本示例在地图上显示以下 POI(中心的默认图像)。

mapicon 的地图

以下代码行显示 MapIcon ,其中包含保存在项目的 Assets 文件夹中的自定义图像。 MapIconImage 属性需要 RandomAccessStreamReference 类型的值。 此类型需要 Windows.Storage.Streams 命名空间的 using 语句。

注意

如果将同一图像用于多个地图图标,请在页面或应用级别声明 RandomAccessStreamReference 以获取最佳性能。

    MapIcon1.Image =
        RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/customicon.png"));

使用 MapIcon 类时,请记住以下注意事项:

添加 3D 图钉

可以在地图中添加三维对象。 使用 MapModel3D 类从 3D 制造格式 (3MF) 文件导入 3D 对象。

此图像使用 3D 咖啡杯来标记附近咖啡店的位置。

地图上的 mugs

以下代码使用导入 3MF 文件将咖啡杯添加到地图。 为了简单起见,此代码会将图像添加到地图的中心,但代码可能会将图像添加到特定位置。

public async void Add3DMapModel()
{
    var mugStreamReference = RandomAccessStreamReference.CreateFromUri
        (new Uri("ms-appx:///Assets/mug.3mf"));

    var myModel = await MapModel3D.CreateFrom3MFAsync(mugStreamReference,
        MapModel3DShadingOption.Smooth);

    myMap.Layers.Add(new MapElementsLayer
    {
       ZIndex = 1,
       MapElements = new List<MapElement>
       {
          new MapElement3D
          {
              Location = myMap.Center,
              Model = myModel,
          },
       },
    });
}

添加图像

显示与地图位置相关的大型图像,例如餐馆或地标的图片。 当用户缩小时,图像将按比例缩小,使用户能够查看更多地图。 这与 MapIcon 稍有不同,它标记特定位置,通常较小,并且与用户放大和缩小地图的大小相同。

MapBillboard 图像

以下代码显示了上图中显示的 MapBillboard

public void AddLandmarkPhoto()
{
    // Create MapBillboard.

    RandomAccessStreamReference mapBillboardStreamReference =
        RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/billboard.jpg"));

    var mapBillboard = new MapBillboard(myMap.ActualCamera)
    {
        Location = myMap.Center,
        NormalizedAnchorPoint = new Point(0.5, 1.0),
        Image = mapBillboardStreamReference
    };

    // Add MapBillboard to a layer on the map control.

    var MyLandmarkPhotos = new List<MapElement>();

    MyLandmarkPhotos.Add(mapBillboard);

    var LandmarksPhotoLayer = new MapElementsLayer
    {
        ZIndex = 1,
        MapElements = MyLandmarkPhotos
    };

    myMap.Layers.Add(LandmarksPhotoLayer);
}

此代码中有三个部分值得仔细检查:图像、引用相机和 NormalizedAnchorPoint 属性。

映像

此示例显示保存在 项目的 Assets 文件夹中的自定义图像。 MapBillboard Image 属性需要 RandomAccessStreamReference 类型的值。 此类型需要 Windows.Storage.Streams 命名空间的 using 语句。

注意

如果将同一图像用于多个地图图标,请在页面或应用级别声明 RandomAccessStreamReference 以获取最佳性能。

参考相机

由于 MapBillboard 图像随着地图缩放级别的变化而缩小,因此必须定义该 ZoomLevel图像以正常 1 倍比例显示的位置。 该位置在 MapBillboard引用相机中定义,若要对其进行设置,则必须将 MapCamera 对象传递到 MapBillboard构造函数中。

可以在 Geopoint定义所需位置,然后使用该 Geopoint 创建 MapCamera 对象。 但是,在此示例中,我们只是使用地图控件的 ActualCamera 属性返回的 MapCamera 对象。 这是地图的内部相机。 该相机的当前位置将成为参考相机位置;MapBillboard 图像以 1 倍比例显示的位置

如果你的应用允许用户缩小地图,图像会减小大小,因为地图内部相机在高度上升,而图像的 1 倍刻度仍固定在参考相机的位置。

NormalizedAnchorPoint

NormalizedAnchorPoint 是定位到 MapBillboard 的 Location 属性的图像点。 点 0.5,1 是图像的底部中心。 由于我们已将 MapBillboardLocation 属性设置为地图控件的中心,因此图像的底部中心将定位在地图控件的中心。 如果希望图像直接在某个点上居中显示,请将 NormalizedAnchorPoint 设置为 0.5,0.5。

添加形状

使用 MapPolygon 类在地图上显示多点形状。 以下示例来自 UWP 地图示例,在地图上显示一个红色框,其中带有蓝色边框。

public void HighlightArea()
{
    // Create MapPolygon.

    double centerLatitude = myMap.Center.Position.Latitude;
    double centerLongitude = myMap.Center.Position.Longitude;

    var mapPolygon = new MapPolygon
    {
        Path = new Geopath(new List<BasicGeoposition> {
                    new BasicGeoposition() {Latitude=centerLatitude+0.0005, Longitude=centerLongitude-0.001 },
                    new BasicGeoposition() {Latitude=centerLatitude-0.0005, Longitude=centerLongitude-0.001 },
                    new BasicGeoposition() {Latitude=centerLatitude-0.0005, Longitude=centerLongitude+0.001 },
                    new BasicGeoposition() {Latitude=centerLatitude+0.0005, Longitude=centerLongitude+0.001 },
                }),
        ZIndex = 1,
        FillColor = Colors.Red,
        StrokeColor = Colors.Blue,
        StrokeThickness = 3,
        StrokeDashed = false,
    };

    // Add MapPolygon to a layer on the map control.
    var MyHighlights = new List<MapElement>();

    MyHighlights.Add(mapPolygon);

    var HighlightsLayer = new MapElementsLayer
    {
        ZIndex = 1,
        MapElements = MyHighlights
    };

    myMap.Layers.Add(HighlightsLayer);
}

添加行

使用 MapPolyline 类在地图上显示一行。 以下示例来自 UWP 地图示例,在地图上显示虚线。

public void DrawLineOnMap()
{
    // Create Polyline.

    double centerLatitude = myMap.Center.Position.Latitude;
    double centerLongitude = myMap.Center.Position.Longitude;
    var mapPolyline = new MapPolyline
    {
        Path = new Geopath(new List<BasicGeoposition> {
                    new BasicGeoposition() {Latitude=centerLatitude-0.0005, Longitude=centerLongitude-0.001 },
                    new BasicGeoposition() {Latitude=centerLatitude+0.0005, Longitude=centerLongitude+0.001 },
                }),
        StrokeColor = Colors.Black,
        StrokeThickness = 3,
        StrokeDashed = true,
    };

   // Add Polyline to a layer on the map control.

   var MyLines = new List<MapElement>();

   MyLines.Add(mapPolyline);

   var LinesLayer = new MapElementsLayer
   {
       ZIndex = 1,
       MapElements = MyLines
   };

   myMap.Layers.Add(LinesLayer);

}

添加 XAML

使用 XAML 在地图上显示自定义 UI 元素。 通过指定 XAML 的位置和规范化定位点在地图上定位 XAML。

以下示例显示了西雅图市的地图,并添加了一个 XAML 边框 控件以指示 Space Needle 的位置。 它还将地图居中位于该区域上并放大。 有关使用地图控件的一般信息,请参阅 显示具有 2D、3D 和街景视图的地图。

private void displayXAMLButton_Click(object sender, RoutedEventArgs e)
{
   // Specify a known location.
   BasicGeoposition snPosition = new BasicGeoposition { Latitude = 47.620, Longitude = -122.349 };
   Geopoint snPoint = new Geopoint(snPosition);

   // Create a XAML border.
   Border border = new Border
   {
      Height = 100,
      Width = 100,
      BorderBrush = new SolidColorBrush(Windows.UI.Colors.Blue),
      BorderThickness = new Thickness(5),
   };

   // Center the map over the POI.
   MapControl1.Center = snPoint;
   MapControl1.ZoomLevel = 14;

   // Add XAML to the map.
   MapControl1.Children.Add(border);
   MapControl.SetLocation(border, snPoint);
   MapControl.SetNormalizedAnchorPoint(border, new Point(0.5, 0.5));
}

本示例在地图上显示蓝色边框。

地图上交点中显示的 xaml 屏幕截图

下一个示例演示如何使用数据绑定直接在页面的 XAML 标记中添加 XAML UI 元素。 与其他显示内容的 XAML 元素一样,Children 是 MapControl 的默认内容属性,不必在 XAML 标记中显式指定。

此示例演示如何将两个 XAML 控件显示为 MapControl隐式子级。 这些控件显示在数据绑定位置的地图上。

<maps:MapControl>
    <TextBox Text="Seattle" maps:MapControl.Location="{x:Bind SeattleLocation}"/>
    <TextBox Text="Bellevue" maps:MapControl.Location="{x:Bind BellevueLocation}"/>
</maps:MapControl>

使用代码隐藏文件中的属性设置这些位置。

public Geopoint SeattleLocation { get; set; }
public Geopoint BellevueLocation { get; set; }

此示例演示如何显示 MapItemsControl 中包含的两个 XAML 控件。这些控件显示在数据绑定位置的地图上。

<maps:MapControl>
  <maps:MapItemsControl>
    <TextBox Text="Seattle" maps:MapControl.Location="{x:Bind SeattleLocation}"/>
    <TextBox Text="Bellevue" maps:MapControl.Location="{x:Bind BellevueLocation}"/>
  </maps:MapItemsControl>
</maps:MapControl>

本示例显示绑定到 MapItemsControl 的 XAML 元素的集合。

<maps:MapControl x:Name="MapControl" MapTapped="MapTapped" MapDoubleTapped="MapTapped" MapHolding="MapTapped">
  <maps:MapItemsControl ItemsSource="{x:Bind LandmarkOverlays}">
      <maps:MapItemsControl.ItemTemplate>
          <DataTemplate>
              <StackPanel Background="Black" Tapped ="Overlay_Tapped">
                  <TextBlock maps:MapControl.Location="{Binding Location}" Text="{Binding Title}"
                    maps:MapControl.NormalizedAnchorPoint="0.5,0.5" FontSize="20" Margin="5"/>
              </StackPanel>
          </DataTemplate>
      </maps:MapItemsControl.ItemTemplate>
  </maps:MapItemsControl>
</maps:MapControl>

ItemsSource上面的示例中的属性绑定到代码隐藏文件中 IList 类型的属性。

public sealed partial class Scenario1 : Page
{
    public IList LandmarkOverlays { get; set; }

    public MyClassConstructor()
    {
         SetLandMarkLocations();
         this.InitializeComponent();   
    }

    private void SetLandMarkLocations()
    {
        LandmarkOverlays = new List<MapElement>();

        var pikePlaceIcon = new MapIcon
        {
            Location = new Geopoint(new BasicGeoposition
            { Latitude = 47.610, Longitude = -122.342 }),
            Title = "Pike Place Market"
        };

        LandmarkOverlays.Add(pikePlaceIcon);

        var SeattleSpaceNeedleIcon = new MapIcon
        {
            Location = new Geopoint(new BasicGeoposition
            { Latitude = 47.6205, Longitude = -122.3493 }),
            Title = "Seattle Space Needle"
        };

        LandmarkOverlays.Add(SeattleSpaceNeedleIcon);
    }
}

使用层

本指南中的示例将元素添加到 MapElementsLayer 集合。 然后,它们演示如何将该集合添加到 地图控件的 Layers 属性。 在以前的版本中,本指南介绍了如何将地图元素添加到 MapElements 集合,如下所示:

var pikePlaceIcon = new MapIcon
{
    Location = new Geopoint(new BasicGeoposition
    { Latitude = 47.610, Longitude = -122.342 }),
    NormalizedAnchorPoint = new Point(0.5, 1.0),
    ZIndex = 0,
    Title = "Pike Place Market"
};

myMap.MapElements.Add(pikePlaceIcon);

虽然仍然可以使用此方法,但会错过新地图层模型的某些优势。 通过将元素分组到层中,可以独立于彼此操作每个层。 例如,每个层都有自己的事件组,你可以响应特定层的事件,并执行特定于该事件的操作。

此外,还可以将 XAML 直接绑定到 MapLayer。 这是使用 MapElements 集合无法实现的。

执行此操作的一种方法是使用视图模型类、XAML 页面背后的代码和 XAML 页面。

查看模型类

public class LandmarksViewModel
{
    public ObservableCollection<MapLayer> LandmarkLayer
        { get; } = new ObservableCollection<MapLayer>();

    public LandmarksViewModel()
    {
        var MyElements = new List<MapElement>();

        var pikePlaceIcon = new MapIcon
        {
            Location = new Geopoint(new BasicGeoposition
            { Latitude = 47.610, Longitude = -122.342 }),
            Title = "Pike Place Market"
        };

        MyElements.Add(pikePlaceIcon);

        var LandmarksLayer = new MapElementsLayer
        {
            ZIndex = 1,
            MapElements = MyElements
        };

        LandmarkLayer.Add(LandmarksLayer);         
    }

XAML 页面背后的代码

将视图模型类连接到代码隐藏页。

public LandmarksViewModel ViewModel { get; set; }

public myMapPage()
{
    this.InitializeComponent();
    this.ViewModel = new LandmarksViewModel();
}

XAML 页

在 XAML 页面中,绑定到返回层的视图模型类中的属性。

<maps:MapControl
    x:Name="myMap" TransitFeaturesVisible="False" Loaded="MyMap_Loaded" Grid.Row="2"
    MapServiceToken="Your token" Layers="{x:Bind ViewModel.LandmarkLayer}"/>