[UWP开发]简单的地图导航应用开发

[UWP开发]简单的地图导航应用开发

在一些应用中,需要有地图位置定位及前往该位置的路径导航功能。地图功能可以调用Windows地图实现。但调用Windows地图需要涉及应用切换,对于用户使用并不友好。需要通过在应用中加入地图来实现。


1 . 直接调用Windows地图
直接调用Windows地图功能使用特定的URI,包括bingmaps:,ms-drive-to:及ms-walk-to: 。具体的URI说明请参考说明文档。
给一个例子,步行从使用者所在的位置(定位)导航到给定坐标,名叫“北山”的地点:

Uri uri = new Uri(@"ms-walk-to:?destination.latitude=31.5035866365965&destination.longitude=112.523597655425&destination.name=北山");
var launcherOptions = new Windows.System.LauncherOptions();
launcherOptions.TargetApplicationPackageFamilyName = "Microsoft.WindowsMaps_8wekyb3d8bbwe";
var success = await Windows.System.Launcher.LaunchUriAsync(uri, launcherOptions);

2 .显示地图
在应用中显示地图,首先需要注册一个必应地图开发者账号,创建应用,获取密钥。
地图使用MapControl控件,在Xaml中引入命名空间。

xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"

添加地图控件。MapServiceToken为你的密钥。

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

3 .设置地图信息
设置地图中心,缩放比例等信息。

//地图中心
BasicGeoposition cityPosition = new BasicGeoposition() { Latitude = 31.5035866365965, Longitude = 112.523597655425 };
Geopoint cityCenter = new Geopoint(cityPosition);
MapControl1.Center = cityCenter;
//其他信息
MapControl1.ZoomLevel = 15;
MapControl1.LandmarksVisible = true;

显示地图及设置地图信息更详细的说明,可以参考文档。文档后面的街景视图等内容,只有国外的区域能用,基本可以不用考虑。

4 .定位
获取用户的位置信息,需要定位权限。首先要在应用包设置中选中“位置”,允许权限。
当用户第一次使用此应用定位时,还会弹出对话框,是否允许使用位置信息。该权限可以在设备的设置->隐私->位置中更改。

Geopoint MyLoc = null;
var accessStatus = await Geolocator.RequestAccessAsync();

switch (accessStatus)
{
    //获取位置权限成功
    case GeolocationAccessStatus.Allowed:
        Geolocator geolocator = new Geolocator();
        Geoposition pos = await geolocator.GetGeopositionAsync();
        MyLoc = pos.Coordinate.Point;
        break;
    case GeolocationAccessStatus.Denied:
        break;
    case GeolocationAccessStatus.Unspecified:
        break;
}

5 .添加地图标记
对于给定的坐标在地图上添加标记。

MapIcon mapIcon1 = new MapIcon();
mapIcon1.Location = cityCenter;  //位置坐标
mapIcon1.NormalizedAnchorPoint = new Point(0.5, 1.0);
mapIcon1.Title = "北山";
mapIcon1.ZIndex = 0;
mapIcon1.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/logosmall.png"));  //使用特定图片作为地图标记,不写这条语句则使用默认标记

添加直线及以XAML元素作为地图标记的方法,参考文档。

6 .导航
给定两个位置坐标,获取驾车路线或者步行路线。

MapRouteFinderResult routeResult =
    await MapRouteFinder.GetDrivingRouteAsync(
    MyLoc,  //位置1
    cityCenter,  //位置2
    MapRouteOptimization.Time,  //以时间最少为优先选择条件
    MapRouteRestrictions.None);  //无其他限制条件(不走高速等)

if (routeResult.Status == MapRouteFinderStatus.Success)
{
    double length = routeResult.Route.LengthInMeters;
    //距离
    Tb_Distance.Text = length < 1000 ? length.ToString() + "m" : (length / 1000).ToString("0.00") + "km";
    //时间
    Tb_Time.Text = routeResult.Route.EstimatedDuration.TotalMinutes.ToString("0.00") + "分钟";

    //在地图上标记出此路线(路线以给定颜色高亮显示)
    MapRouteView viewOfRoute = new MapRouteView(routeResult.Route);
    viewOfRoute.RouteColor = Color.FromArgb(255, 26, 188, 156);
    MapControl1.Routes.Clear();
    MapControl1.Routes.Add(viewOfRoute);
    await MapControl1.TrySetViewBoundsAsync(
        routeResult.Route.BoundingBox,
        ull,
        Windows.UI.Xaml.Controls.Maps.MapAnimationKind.None);

    //自定义类,用于存放路径中部分有用的信息。
    List RI = new List();
    System.Text.StringBuilder routeInfo = new System.Text.StringBuilder();
    foreach (MapRouteLeg leg in routeResult.Route.Legs)
    {
        foreach (MapRouteManeuver maneuver in leg.Maneuvers)
        {
            RI.Add(new RouteItem(maneuver.InstructionText, maneuver.LengthInMeters + "m", maneuver.StartingPoint));
        }
    }
}
else if(routeResult.Status == MapRouteFinderStatus.NetworkFailure);

RouteItem定义如下:

public class RouteItem
{
    public RouteItem(string direction, string length, Geopoint point)
    {
        Direction = direction;
        Length = length;
        Point = point;
    }

    public string Direction { get; set; }  //逐步导航信息
    public string Length { get; set; }  //该步骤执行后走的距离,到下一步骤
    public Geopoint Point { get; set; }  //执行该步骤的起始点坐标
}

执行步行导航,只需要将MapRouteFinder.GetDrivingRouteAsync替换为

MapRouteFinderResult routeResult =
    await MapRouteFinder.GetWalkingRouteAsync(
    MyLoc,
    cityCenter);

其他代码相同。
获取导航路径这一部分可以参考文档。

7 .逐步导航的界面呈现
XAML中定义Item模板。绑定上一步中获取的逐步导航信息,到界面呈现。

<DataTemplate x:Key="RouteTemplate" x:DataType="local:RouteItem">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*">ColumnDefinition>
            <ColumnDefinition Width="auto">ColumnDefinition>
        Grid.ColumnDefinitions>
        <TextBlock Text="{x:Bind Direction}" Grid.Column="0" TextWrapping="Wrap" MaxWidth="300" HorizontalAlignment="Left">TextBlock>
        <TextBlock Text="{x:Bind Length}" Grid.Column="1" TextWrapping="Wrap" HorizontalAlignment="Right">TextBlock>
    Grid>
DataTemplate>

呈现结果为下图所示的列表。
[UWP开发]简单的地图导航应用开发_第1张图片
当点击一个列表项的时候,触发事件。在地图上标记该步骤。

private void Lv_Route_ItemClick(object sender, ItemClickEventArgs e)
{
    var item = e.ClickedItem as RouteItem;

    //清除已有的标记
    MapControl1.MapElements.Clear();

    //添加新的点标记
    MapIcon mapIcon1 = new MapIcon();
    mapIcon1.Location = item.Point;
    mapIcon1.NormalizedAnchorPoint = new Point(0.5, 1.0);
    mapIcon1.Title = item.Direction;
    mapIcon1.ZIndex = 0;
    MapControl1.MapElements.Add(mapIcon1);
}

8 .实时导航
实时导航需要响应用户位置更新,并更新导航结果。这个功能在一般的附加地图位置分享功能的应用中,几乎不需要用到。只有在以地图为主的应用中用到。如果需要用到这一功能,建议跳转到Windows地图应用来实现。如果要自己写这一功能,可以参考文档,不再介绍。


代码通过Visual Studio 2017测试。

你可能感兴趣的:(Windows应用商店)