使用 2D、3D 和街景视图显示地图Display maps with 2D, 3D, and Streetside views

你可以在名为地图地点卡 的可轻型消除窗口中或在功能齐全的地图控件中显示地图。You can show a map in light dismissable window called a map placecard or in a full featured map control.

下载地图示例来尝试本指南中所述的一些功能。Download the map sample to try out some the features described in this guide.

在地点卡中显示地图Display map in a placecard

在上面的轻型弹出窗口中,你可以将地图展示在 UI 元素的上方、下方或侧面,或者展示在应用中用户触摸的区域。You can show users a map inside of a light-weight pop-up window above, below or to the side of a UI element or an area of an app where the user touches. 地图可以显示与你的应用中的信息相关的城市或地址。The map can show a city or address that relates to information in your app.

此地点卡显示西雅图市。This placecard shows the city of Seattle.

显示西雅图市的地点卡

以下代码可在一个按钮下方的地点卡中显示西雅图。Here's the code that makes Seattle appear in a placecard below a button.

private void Seattle_Click(object sender, RoutedEventArgs e)
{
    Geopoint seattlePoint = new Geopoint
        (new BasicGeoposition { Latitude = 47.6062, Longitude = -122.3321 });

    PlaceInfo spaceNeedlePlace = PlaceInfo.Create(seattlePoint);

    FrameworkElement targetElement = (FrameworkElement)sender;

    GeneralTransform generalTransform =
        targetElement.TransformToVisual((FrameworkElement)targetElement.Parent);

    Rect rectangle = generalTransform.TransformBounds(new Rect(new Point
        (targetElement.Margin.Left, targetElement.Margin.Top), targetElement.RenderSize));

    spaceNeedlePlace.Show(rectangle, Windows.UI.Popups.Placement.Below);
}

此地点卡显示西雅图太空针塔的位置。This placecard shows the location of the Space Needle in Seattle.

显示太空针塔位置的地点卡

以下代码可在一个按钮下方的地点卡中显示太空针塔。Here's the code that makes the Space Needle appear in a placecard below a button.

private void SpaceNeedle_Click(object sender, RoutedEventArgs e)
{
    Geopoint spaceNeedlePoint = new Geopoint
        (new BasicGeoposition { Latitude = 47.6205, Longitude = -122.3493 });

    PlaceInfoCreateOptions options = new PlaceInfoCreateOptions();

    options.DisplayAddress = "400 Broad St, Seattle, WA 98109";
    options.DisplayName = "Seattle Space Needle";

    PlaceInfo spaceNeedlePlace =  PlaceInfo.Create(spaceNeedlePoint, options);

    FrameworkElement targetElement = (FrameworkElement)sender;

    GeneralTransform generalTransform =
        targetElement.TransformToVisual((FrameworkElement)targetElement.Parent);

    Rect rectangle = generalTransform.TransformBounds(new Rect(new Point
        (targetElement.Margin.Left, targetElement.Margin.Top), targetElement.RenderSize));

    spaceNeedlePlace.Show(rectangle, Windows.UI.Popups.Placement.Below);
}

在控件中显示地图Display map in a control

在你的应用中使用地图控件来显示丰富且可自定义的地图数据。Use a map control to show rich and customizable map data in your app. 地图控件可以显示道路地图、鸟瞰图、3D、视图、路线、搜索结果和交通。A map control can display road maps, aerial, 3D, views, directions, search results, and traffic. 在地图上,你可以显示用户的位置、路线和目标点。On a map, you can display the user's location, directions, and points of interest. 地图还可以显示 3D 鸟瞰图、街景视图、交通、公交和本地企业。A map can also show aerial 3D views, Streetside views, traffic, transit, and local businesses.

当你希望应用内具有一个允许用户查看特定于应用或通用地理信息的地图时,请使用地图控件。Use a map control when you want a map within your app that allows users to view app-specific or general geographic information. 在应用中有一个地图控件意味着用户无需为了获取该信息而离开应用。Having a map control in your app means that users don't have to go outside your app to get that information.

向应用中添加地图控件Add a map control to your app

通过添加 MapControl 在 XAML 页面上显示地图。Display a map on a XAML page by adding a MapControl. 若要使用 MapControl,你必须在 XAML 页面或代码中声明 Windows.UI.Xaml.Controls.Maps 命名空间。To use the MapControl, you must declare the Windows.UI.Xaml.Controls.Maps namespace in the XAML page or in your code. 如果你从工具箱中拖动控件,此命名空间声明将自动添加。If you drag the control from the Toolbox, this namespace declaration is added automatically. 如果你手动将 MapControl 添加到 XAML 页面,则必须在该页面顶部手动添加命名空间声明。If you add the MapControl to the XAML page manually, you must add the namespace declaration manually at the top of the page.

以下示例显示基本地图控件,以及配置地图以便除了接受触摸输入之外,还显示缩放和倾斜控件。The following example displays a basic map control and configures the map to display the zoom and tilt controls in addition to accepting touch inputs.

<Page
    x:Class="MapsAndLocation1.DisplayMaps"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MapsAndLocation1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
    mc:Ignorable="d">

 <Grid x:Name="pageGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Maps:MapControl
       x:Name="MapControl1"            
       ZoomInteractionMode="GestureAndControl"
       TiltInteractionMode="GestureAndControl"   
       MapServiceToken="EnterYourAuthenticationKeyHere"/>

 </Grid>
</Page>

如果在你的代码中添加地图控件,则必须在该代码文件顶部手动声明命名空间。If you add the map control in your code, you must declare the namespace manually at the top of the code file.

using Windows.UI.Xaml.Controls.Maps;
...

// Add the MapControl and the specify maps authentication key.
MapControl MapControl2 = new MapControl();
MapControl2.ZoomInteractionMode = MapInteractionMode.GestureAndControl;
MapControl2.TiltInteractionMode = MapInteractionMode.GestureAndControl;
MapControl2.MapServiceToken = "EnterYourAuthenticationKeyHere";
pageGrid.Children.Add(MapControl2);

获取和设置地图验证密钥Get and set a maps authentication key

在可以使用 MapControl 和地图服务之前,你必须将地图身份验证密钥指定为 MapServiceToken 属性的值。Before you can use MapControl and map services, you must specify the maps authentication key as the value of the MapServiceToken property. 在上一个示例中,将 EnterYourAuthenticationKeyHere 替换为你从必应地图开发人员中心获取的密钥。In the previous examples, replace EnterYourAuthenticationKeyHere with the key you get from the Bing Maps Developer Center. 在你指定地图身份验证密钥之前,文本 “警告:未指定 MapServiceToken” 会继续显示在控件下方。The text Warning: MapServiceToken not specified continues to appear below the control until you specify the maps authentication key. 有关获取和设置地图身份验证密钥的详细信息,请参阅请求地图身份验证密钥For more info about getting and setting a maps authentication key, see Request a maps authentication key.

设置地图的位置Set the location of a map

将地图指向你所需的任何位置,或使用用户的当前位置。Point the map to any location that you want or use the user's current location.

设置地图的起始位置Set a starting location for the map

在地图上设置要显示的位置,方法为在代码中指定 MapControlCenter 属性或在 XAML 标记中绑定属性。Set the location to display on the map by specifying the Center property of the MapControl in your code or by binding the property in your XAML markup. 以下示例以西雅图市为中心显示地图。The following example displays a map with the city of Seattle as its center.

备注

由于字符串不能转换为 Geopoint,因此无法在 XAML 标记中为 Center 属性指定值,除非使用数据绑定。Since a string can't be converted to a Geopoint, you can't specify a value for the Center property in XAML markup unless you use data binding. (此限制同样适用于 MapControl.Location 附加属性。)(This limitation also applies to the MapControl.Location attached property.)

 

protected override void OnNavigatedTo(NavigationEventArgs e)
{
   // Specify a known location.
   BasicGeoposition cityPosition = new BasicGeoposition() { Latitude = 47.604, Longitude = -122.329 };
   Geopoint cityCenter = new Geopoint(cityPosition);

   // Set the map location.
   MapControl1.Center = cityCenter;
   MapControl1.ZoomLevel = 12;
   MapControl1.LandmarksVisible = true;
}

地图控件的示例。

设置地图的当前位置Set the current location of the map

在应用可以访问用户位置之前,你的应用必须调用 RequestAccessAsync 方法。Before your app can access the user’s location, your app must call the RequestAccessAsync method. 此时,你的应用必须位于前台,并且 RequestAccessAsync 必须从 UI 线程中进行调用。At that time, your app must be in the foreground and RequestAccessAsync must be called from the UI thread. 除非用户向你的应用授予访问其位置的权限,否则你的应用将无法访问位置数据。Until the user grants your app permission to their location, your app can't access location data.

使用 Geolocator 类的 GetGeopositionAsync 方法获取设备的当前位置(如果位置可用)。Get the current location of the device (if location is available) by using the GetGeopositionAsync method of the Geolocator class. 若要获取相应的 Geopoint,请使用地理位置的地理坐标的 Point 属性。To obtain the corresponding Geopoint, use the Point property of the geoposition's geocoordinate. 有关详细信息,请参阅获取当前位置For more info, see Get current location.

// Set your current location.
var accessStatus = await Geolocator.RequestAccessAsync();
switch (accessStatus)
{
   case GeolocationAccessStatus.Allowed:

      // Get the current location.
      Geolocator geolocator = new Geolocator();
      Geoposition pos = await geolocator.GetGeopositionAsync();
      Geopoint myLocation = pos.Coordinate.Point;

      // Set the map location.
      MapControl1.Center = myLocation;
      MapControl1.ZoomLevel = 12;
      MapControl1.LandmarksVisible = true;
      break;

   case GeolocationAccessStatus.Denied:
      // Handle the case  if access to location is denied.
      break;

   case GeolocationAccessStatus.Unspecified:
      // Handle the case if  an unspecified error occurs.
      break;
}

当在地图上显示设备位置时,请考虑显示图形,并根据该位置数据的精确度设置缩放级别。When you display your device's location on a map, consider displaying graphics and setting the zoom level based on the accuracy of the location data. 有关详细信息,请参阅位置感知应用指南For more info, see Guidelines for location-aware apps.

更改地图的位置Change the location of the map

若要更改在 2D 地图中显示的位置,请调用其中一个 TrySetViewAsync 方法的重载。To change the location that appears in a 2D map, call one of the overloads of the TrySetViewAsync method. 使用该方法以指定 CenterZoomLevelHeadingPitch 的新值。Use that method to specify new values for Center, ZoomLevel, Heading, and Pitch. 你也可以在查看更改时,通过提供一个来自 MapAnimationKind 枚举的常数,指定要使用的可选动画。You can also specify an optional animation to use when the view changes by providing a constant from the MapAnimationKind enumeration.

若要更改 3D 地图的位置,请改为使用 TrySetSceneAsync 方法。To change the location of a 3D map, use the TrySetSceneAsync method instead. 有关详细信息,请参阅显示鸟瞰图 3D 视图For more info, see Display aerial 3D views.

调用 TrySetViewBoundsAsync 方法以在地图上显示 GeoboundingBox 的内容。Call the TrySetViewBoundsAsync method to display the contents of a GeoboundingBox on the map. 例如,使用此方法可在地图上显示路线或部分路线。Use this method, for example, to display a route or a portion of a route on the map. 有关详细信息,请参阅在地图上显示路线和方向For more info, see Display routes and directions on a map.

更改地图的外观Change the appearance of a map

要自定义地图的外观,请将地图控件的 StyleSheet 属性设置为任何现有 MapStyleSheet 对象。To customize the look and feel of the map, set the StyleSheet property of the map control to any of the existing MapStyleSheet objects.

myMap.StyleSheet = MapStyleSheet.RoadDark();

深色样式地图

你还可以使用 JSON 来定义自定义样式,然后使用该 JSON 创建 MapStyleSheet对象。You can also use JSON to define custom styles and then use that JSON to create a MapStyleSheet object.

可以使用 "地图样式表编辑器" 应用程序以交互方式创建样式表 JSON。Style sheet JSON can be created interactively using the Map Style Sheet Editor application.

myMap.StyleSheet = MapStyleSheet.ParseFromJson(@"
    {
        ""version"": ""1.0"",
        ""settings"": {
            ""landColor"": ""#FFFFFF"",
            ""spaceColor"": ""#000000""
        },
        ""elements"": {
            ""mapElement"": {
                ""labelColor"": ""#000000"",
                ""labelOutlineColor"": ""#FFFFFF""
            },
            ""water"": {
                ""fillColor"": ""#DDDDDD""
            },
            ""area"": {
                ""fillColor"": ""#EEEEEE""
            },
            ""political"": {
                ""borderStrokeColor"": ""#CCCCCC"",
                ""borderOutlineColor"": ""#00000000""
            }
        }
    }
");

自定义样式地图

有关完整 JSON 条目参考,请参阅地图样式表参考For the complete JSON entry reference, see Map style sheet reference.

你可以基于现有样式表开始自定义,然后根据具体需要使用 JSON 覆盖任何元素。You can start with an existing sheet and then use JSON to override any elements that you want. 此示例就使用了一个现有的样式开始自定义,并使用 JSON 仅更改水域的颜色。This example, starts with an existing style and uses JSON to change only the color of water areas.

 MapStyleSheet \customSheet = MapStyleSheet.ParseFromJson(@"
    {
        ""version"": ""1.0"",
        ""elements"": {
            ""water"": {
                ""fillColor"": ""#DDDDDD""
            }
        }
    }
");

MapStyleSheet builtInSheet = MapStyleSheet.RoadDark();

myMap.StyleSheet = MapStyleSheet.Combine(new List<MapStyleSheet> { builtInSheet, customSheet });

结合样式地图

备注

你在第二个样式表中定义的样式会覆盖第一个样式表中的样式。Styles that you define in the second style sheet override the styles in the first.

设置方向和角度Set orientation and perspective

放大、缩小、旋转和倾斜地图的照相机,调整为你所需效果的相应角度。Zoom in, zoom out, rotate, and tilt the map's camera to get just the right angle for the effect that you want. 尝试这些属性。Try these properties.

显示和隐藏地图功能Show and hide map features

通过设置以下 MapControl 属性的值显示或隐藏地图功能,如道路和地标。Show or hide map features such as roads and landmarks by setting the values of the following properties of the MapControl.

有关如何显示图钉、图形和 MapControl 中的 XAML 控件的详细信息,请参阅在地图上显示目标点 (POI)For info about how to display pushpins, shapes, and XAML controls in the MapControl, see Display points of interest (POI) on a map.

显示街景视图Display Streetside views

街景视图是显示在地图控件顶部的位置的街景级视角。A Streetside view is a street-level perspective of a location that appears on top of the map control.

地图控件的街景视图的示例。

考虑“内部”街景视图与地图控件中最初显示的地图有所不同的体验。Consider the experience "inside" the Streetside view separate from the map originally displayed in the map control. 例如,更改街景视图中的位置不会改变街景视图“之下”的地图的位置或外观。For example, changing the location in the Streetside view does not change the location or appearance of the map "under" the Streetside view. 在你关闭街景视图(通过单击控件右上角的“X”)之后,原始地图将保持不变。After you close the Streetside view (by clicking the X in the upper right corner of the control), the original map remains unchanged.

显示街景视图To display a Streetside view

  1. 通过检查 IsStreetsideSupported 来确定街景视图在设备上是否受支持。Determine if Streetside views are supported on the device by checking IsStreetsideSupported.
  2. 如果支持街景视图,请通过调用 FindNearbyAsync 在指定位置附近创建 StreetsidePanoramaIf Streetside view is supported, create a StreetsidePanorama near the specified location by calling FindNearbyAsync.
  3. 通过检查 StreetsidePanorama 是否不为空来确定是否可以找到附近全景。Determine if a nearby panorama was found by checking if the StreetsidePanorama is not null
  4. 如果找到附近全景,则创建地图控件的 CustomExperience 属性的 StreetsideExperienceIf a nearby panorama was found, create a StreetsideExperience for the map control's CustomExperience property.

此示例介绍如何显示类似于上一个图像的街景视图。This example shows how to display a Streetside view similar to the previous image.

请注意  如果地图控件大小太小,则不会显示 "概述" 地图。Note  The overview map will not appear if the map control is sized too small.

 

private async void showStreetsideView()
{
   // Check if Streetside is supported.
   if (MapControl1.IsStreetsideSupported)
   {
      // Find a panorama near Avenue Gustave Eiffel.
      BasicGeoposition cityPosition = new BasicGeoposition() { Latitude = 48.858, Longitude = 2.295};
      Geopoint cityCenter = new Geopoint(cityPosition);
      StreetsidePanorama panoramaNearCity = await StreetsidePanorama.FindNearbyAsync(cityCenter);

      // Set the Streetside view if a panorama exists.
      if (panoramaNearCity != null)
      {
         // Create the Streetside view.
         StreetsideExperience ssView = new StreetsideExperience(panoramaNearCity);
         ssView.OverviewMapVisible = true;
         MapControl1.CustomExperience = ssView;
      }
   }
   else
   {
      // If Streetside is not supported
      ContentDialog viewNotSupportedDialog = new ContentDialog()
      {
         Title = "Streetside is not supported",
         Content ="\nStreetside views are not supported on this device.",
         PrimaryButtonText = "OK"
      };
      await viewNotSupportedDialog.ShowAsync();            
   }
}
## 显示鸟瞰图 3D 视图Display aerial 3D views

使用 MapScene 类指定地图的 3D 视角。Specify a 3D perspective of the map by using the MapScene class. 地图场景表示显示在地图上的 3D 视图。The map scene represents the 3D view that appears in the map. MapCamera 类表示可能显示如此一个视图的相机的位置。The MapCamera class represents the position of the camera that would display such a view.

MapCamera 位置与地图场景位置图示

若要使地图表面上的建筑物和其他功能以 3D 方式显示,请将地图控件的 Style 属性设置为 MapStyle.Aerial3DWithRoadsTo make buildings and other features on the map surface appear in 3D, set the map control's Style property to MapStyle.Aerial3DWithRoads. 这是一个以 Aerial3DWithRoads 样式显示 3D 视图的示例。This is an example of a 3D view with the Aerial3DWithRoads style.

3D 地图视图的示例。

显示 3D 视图To display a 3D view

  1. 通过检查 Is3DSupported 来确定 3D 视图在设备上是否受支持。Determine if 3D views are supported on the device by checking Is3DSupported.
  2. 如果支持 3D 视图,请将地图控件的 Style 属性设置为 MapStyle.Aerial3DWithRoadsIf 3D views is supported, set the map control's Style property to MapStyle.Aerial3DWithRoads.
  3. 使用许多 CreateFrom方法之一(例如CreateFromLocationAndRadius 和 CreateFromCamera)创建 MapScene 对象。Create a MapScene object using one of the many CreateFrom methods, such as CreateFromLocationAndRadius and CreateFromCamera.
  4. 调用 TrySetSceneAsync 以显示 3D 视图。Call TrySetSceneAsync to display the 3D view. 你也可以在查看更改时,通过提供一个来自 MapAnimationKind 枚举的常数,指定要使用的可选动画。You can also specify an optional animation to use when the view changes by providing a constant from the MapAnimationKind enumeration.

此示例介绍如何显示 3D 视图。This example shows how to display a 3D view.

private async void display3DLocation()
{
   if (MapControl1.Is3DSupported)
   {
      // Set the aerial 3D view.
      MapControl1.Style = MapStyle.Aerial3DWithRoads;

      // Specify the location.
      BasicGeoposition hwGeoposition = new BasicGeoposition() { Latitude = 43.773251, Longitude = 11.255474};
      Geopoint hwPoint = new Geopoint(hwGeoposition);

      // Create the map scene.
      MapScene hwScene = MapScene.CreateFromLocationAndRadius(hwPoint,
                                                                           80, /* show this many meters around */
                                                                           0, /* looking at it to the North*/
                                                                           60 /* degrees pitch */);
      // Set the 3D view with animation.
      await MapControl1.TrySetSceneAsync(hwScene,MapAnimationKind.Bow);
   }
   else
   {
      // If 3D views are not supported, display dialog.
      ContentDialog viewNotSupportedDialog = new ContentDialog()
      {
         Title = "3D is not supported",
         Content = "\n3D views are not supported on this device.",
         PrimaryButtonText = "OK"
      };
      await viewNotSupportedDialog.ShowAsync();
   }
}

获取有关位置的信息Get info about locations

通过调用 MapControl 的以下方法,在地图上获取有关位置的信息。Get info about locations on the map by calling the following methods of the MapControl.

  • TryGetLocationFromOffset方法-获取与地图控件的视区中的指定点相对应的地理位置。TryGetLocationFromOffset method - Get the geographic location that corresponds to the specified point in the viewport of the Map control.
  • GetOffsetFromLocation方法-获取对应于指定地理位置的地图控件视区中的点。GetOffsetFromLocation method - Get the point in the viewport of the Map control that corresponds to the specified geographic location.
  • IsLocationInView方法-确定指定的地理位置当前在地图控件的视区中是否可见。IsLocationInView method - Determine whether the specified geographic location is currently visible in the viewport of the Map control.
  • FindMapElementsAtOffset方法-获取位于地图控件的视区中指定点的地图上的元素。FindMapElementsAtOffset method - Get the elements on the map located at the specified point in the viewport of the Map control.

处理交互和更改Handle interaction and changes

通过处理 MapControl 的以下事件,处理地图上的用户输入手势。Handle user input gestures on the map by handling the following events of the MapControl. 通过检查 MapInputEventArgsLocationPosition 属性的值,获取有关地图上的地理位置和出现手势的视口所在的物理位置的信息。Get info about the geographic location on the map and the physical position in the viewport where the gesture occurred by checking the values of the Location and Position properties of the MapInputEventArgs.

通过处理控件的 LoadingStatusChanged 事件,确定地图是正在加载还是已完全加载。Determine whether the map is loading or completely loaded by handling the control's LoadingStatusChanged event.

通过处理 MapControl 的以下事件,处理用户或应用更改地图的设置时所发生的更改。Handle changes that happen when the user or the app changes the settings of the map by handling the following events of the MapControl. 地图准则Guidelines for maps

最佳做法建议Best practice recommendations

  • 使用充足的屏幕空间(或整个屏幕)显示地图,以便用户无需过度平移和缩放来查看地理信息。Use ample screen space (or the entire screen) to display the map so that users don't have to pan and zoom excessively to view geographical information.

  • 如果地图仅用于呈现静态的、信息性的视图,则使用较小的地图可能更合适。If the map is only used to present a static, informational view, then using a smaller map might be more appropriate. 如果你选择较小的静态地图,请根据可用性设置其维度:小到足够节省屏幕空间,大到足够保持清晰。If you go with a smaller, static map, base its dimensions on usability—small enough to conserve enough screen real estate, but large enough to remain legible.

  • 使用 map elements 在地图场景中嵌入目标点;任何其他信息都可作为覆盖地图场景的瞬态 UI 显示。Embed the points of interest in the map scene using map elements; any additional information can be displayed as transient UI that overlays the map scene.