WPF 加载高德地图时疑问解答
控件名:AMap
作 者:WPFDevelopersOrg - 驚鏵
原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers
框架使用
.NET4 至 .NET6
;Visual Studio 2022
;感谢各位开发者对加载卫星地图的问题的提问和在GitHub上提交的issue[2]。我们很乐意为你提供帮助,并分享一个简单的示例代码来加载卫星地图。
高德地图的瓦片(Tile)服务地址http://wprd01.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scl=1&style={3},用于获取地图瓦片的图像数据。以下参数的描述:
{0}
: 表示瓦片的X坐标,用于指定地图瓦片在水平方向上的位置。{1}
: 表示瓦片的Y坐标,用于指定地图瓦片在垂直方向上的位置。{2}
: 表示瓦片的缩放级别(Zoom Level),用于指定地图的显示级别。
其他参数:
lang=zh_cn
: 指定地图语言为简体中文。size=1
: 指定瓦片的尺寸为1,表示返回的瓦片图像大小为256x256像素。scl=1
: 指定瓦片的比例尺为1,表示返回的瓦片图像不进行缩放。style=7
: 指定地图的样式,需要显示卫星地图需要修改style
。以下是一些常见的style参数值及其对应的地图样式:
style=6
:卫星地图,显示卫星影像。style=7
:标准地图,包含道路、建筑物和自然地理特征。style=8
:带有主要道路名称的标准地图。style=9
:深色背景地图,适合夜间显示。style=10
:蓝色主题地图,强调水域和海洋。
1)新增 AMapTitleLayer.cs
代码如下:
using Microsoft.Maps.MapControl.WPF;
using System;
namespace WPFDevelopers.Samples.ExampleViews
{
public class AMapTitleLayer : MapTileLayer
{
private AMapTileSource tileSource;
public AMapTitleLayer()
{
tileSource = new AMapTileSource();
TileSource = tileSource;
}
public string UriFormat
{
get { return TileSource.UriFormat; }
set { TileSource.UriFormat = value; }
}
public void UpdateTileSourceStyle(int style)
{
tileSource.UpdateStyle(style);
}
}
public class AMapTileSource : TileSource
{
private int style = 7;
public override Uri GetUri(int x, int y, int zoomLevel)
{
string url = string.Format("http://wprd01.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scl=1&style={3}", x, y, zoomLevel, style);
return new Uri(url, UriKind.Absolute);
}
public void UpdateStyle(int newStyle)
{
if (newStyle == style) return;
style = newStyle;
}
}
}
2)新增 PushpinModel.cs
代码如下:
using Microsoft.Maps.MapControl.WPF;
namespace WPFDevelopers.Samples.ExampleViews
{
public class PushpinModel
{
public Location Location { get; set; }
public int ID { get; set; }
public string Title { get; set; }
}
}
3)新增 BingAMapExample.xaml
代码如下:
<UserControl
x:Class="WPFDevelopers.Samples.ExampleViews.BingAMapExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
xmlns:map="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
xmlns:mapOverlays="clr-namespace:Microsoft.Maps.MapControl.WPF.Overlays;assembly=Microsoft.Maps.MapControl.WPF"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=System"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources>
<LinearGradientBrush x:Key="MainColor" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FF020621" />
<GradientStop Offset="1" Color="#FF364BD8" />
<GradientStop Offset="0.499" Color="#FF5A6BD8" />
</LinearGradientBrush>
<ControlTemplate x:Key="CarTemplate" TargetType="map:Pushpin">
<Grid ToolTip="物资车辆">
<Ellipse
Width="35"
Height="35"
Fill="White"
Stroke="Red"
StrokeThickness="3" />
<Image
Width="25"
Height="25"
Source="pack://application:,,,/WPFDevelopers.Samples;component/Resources/Images/AMap/Car2.png" />
</Grid>
</ControlTemplate>
<SineEase x:Key="SineOut" EasingMode="EaseOut" />
<Storyboard x:Key="AnimateRound" RepeatBehavior="Forever">
<DoubleAnimation
EasingFunction="{StaticResource WD.SineEaseOut}"
Storyboard.TargetName="Scale"
Storyboard.TargetProperty="ScaleX"
To="2"
Duration="0:0:01" />
<DoubleAnimation
EasingFunction="{StaticResource WD.SineEaseOut}"
Storyboard.TargetName="Scale"
Storyboard.TargetProperty="ScaleY"
To="2"
Duration="0:0:01" />
<DoubleAnimation
EasingFunction="{StaticResource WD.SineEaseOut}"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:01" />
</Storyboard>
<Style x:Key="alarmStyle" TargetType="map:Pushpin">
<Setter Property="PositionOrigin" Value="Center" />
<Setter Property="Width" Value="60" />
<Setter Property="Height" Value="60" />
<Setter Property="ToolTip" Value="青州市" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="map:Pushpin">
<Grid>
<Ellipse
Width="40"
Height="40"
Fill="Red"
RenderTransformOrigin="0.5,0.5">
<Ellipse.OpacityMask>
<RadialGradientBrush>
<GradientStop Offset="0" Color="Transparent" />
<GradientStop Offset="1" Color="Black" />
</RadialGradientBrush>
</Ellipse.OpacityMask>
<Ellipse.RenderTransform>
<ScaleTransform x:Name="Scale" />
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource AnimateRound}" />
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
<Viewbox
Width="30"
Height="30"
Margin="20,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<Path Data="{StaticResource WD.FlagGeometry}" Fill="Orange" />
</Viewbox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<controls:CodeViewer>
<Grid>
<map:Map
x:Name="map"
Center="39.9132801985722,116.392009995601"
CredentialsProvider="AgXB7m7fVYxKpjEZV9rGdrRPvLgawYhi4Wvw99kk4RDspoalC3B_vQ8GKJAoxrve"
ZoomLevel="5">
<map:Map.Mode>
<map:MercatorMode />
</map:Map.Mode>
<map:MapItemsControl ItemsSource="{Binding PushpinArray, RelativeSource={RelativeSource AncestorType=local:BingAMapExample}}">
<map:MapItemsControl.ItemTemplate>
<DataTemplate>
<map:Pushpin
Background="Red"
Cursor="Hand"
Location="{Binding Location}"
MouseDown="Pushpin_MouseDown"
ToolTip="{Binding Title}">
<TextBlock Text="{Binding ID}" />
</map:Pushpin>
</DataTemplate>
</map:MapItemsControl.ItemTemplate>
</map:MapItemsControl>
<map:Pushpin Location="36.6797276003243,118.495410536117" Style="{StaticResource alarmStyle}" />
<Canvas
Width="50"
Height="80"
map:MapLayer.Position="31.9121578992881,107.233555852083"
map:MapLayer.PositionOrigin="BottomCenter"
Opacity="0.7">
<Path
Data="M 0,0 L 50,0 50,50 25,80 0,50 0,0"
Fill="ForestGreen"
Stroke="Wheat"
StrokeThickness="2" />
<TextBlock
Padding="10"
FontSize="10"
Foreground="White"
TextAlignment="Center">
这里是<LineBreak />
四川<LineBreak />
通江县<LineBreak />
</TextBlock>
</Canvas>
<map:MapLayer x:Name="CarLayer" />
</map:Map>
<DockPanel>
<Grid DockPanel.Dock="Top">
<Path
Width="200"
Height="30"
Data="M75.811064,0 L275.81107,0 275.81107,39.999999 267.12714,39.999999 267.12798,40.000499 67.127973,40.000499 0,0.00050140842 75.811064,0.00050140842 z"
Fill="{StaticResource MainColor}"
Opacity=".8"
Stretch="Fill"
Stroke="#FFCCFEFF"
StrokeThickness="1.5">
<Path.RenderTransform>
<SkewTransform AngleX="-40" />
</Path.RenderTransform>
</Path>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
FontWeight="Black"
Foreground="White"
Text="预警信息平台" />
</Grid>
<Grid
Width="200"
HorizontalAlignment="Left"
DockPanel.Dock="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle
Grid.RowSpan="3"
Fill="#FF364BD8"
Opacity=".8"
Stroke="#FFCCFEFF"
StrokeThickness="1.5" />
<TextBlock
Margin="10,10,0,0"
FontSize="16"
Foreground="White"
Text="数据信息" />
<ItemsControl
Grid.Row="1"
Margin="4,10"
ItemsSource="{Binding PushpinArray, RelativeSource={RelativeSource AncestorType=local:BingAMapExample}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid
x:Name="PART_Grid"
Margin="4"
MouseLeftButtonDown="PART_Grid_MouseLeftButtonDown"
Tag="{Binding ID}">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="16" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Ellipse
Width="20"
Height="20"
Fill="OrangeRed" />
<TextBlock HorizontalAlignment="Center" Text="{Binding ID}" />
<TextBlock
Grid.Column="1"
Margin="4,0"
Text="{Binding Title}" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Grid" Property="Background" Value="#FF020621" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button
Grid.Row="2"
Height="40"
Click="BtnCar_Click"
Content="物资轨迹"
Style="{StaticResource WD.PrimaryButton}" />
</Grid>
</DockPanel>
<ComboBox
Width="120"
HorizontalAlignment="Right"
VerticalAlignment="Top"
DisplayMemberPath="Value"
ItemsSource="{Binding MapStyleDic, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedIndex="1"
SelectedValuePath="Key"
SelectionChanged="StyleComboBox_SelectionChanged" />
</Grid>
<controls:CodeViewer.SourceCodes>
<controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/Map/BingAMapExample.xaml" CodeType="Xaml" />
<controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/Map/BingAMapExample.xaml.cs" CodeType="CSharp" />
<controls:SourceCodeModel
CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/Map/AMapTitleLayer.cs"
CodeType="CSharp"
Haader="TitleLayer" />
<controls:SourceCodeModel
CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/Map/PushpinModel.cs"
CodeType="CSharp"
Haader="Pushpin" />
</controls:CodeViewer.SourceCodes>
</controls:CodeViewer>
</UserControl>
4)新增 BingAMapExample.xaml.cs
代码如下:
using Microsoft.Maps.MapControl.WPF;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace WPFDevelopers.Samples.ExampleViews
{
/// <summary>
/// BingAMapExample.xaml 的交互逻辑
/// </summary>
public partial class BingAMapExample : UserControl
{
private LocationCollection _polyLocations;
private MapPolyline mapPolyline;
private Pushpin carPushpin;
private DispatcherTimer dispatcherTimer;
private List<Location> locations;
private AMapTitleLayer aMapTitleLayer;
public IEnumerable PushpinArray
{
get { return (IEnumerable)GetValue(PushpinArrayProperty); }
set { SetValue(PushpinArrayProperty, value); }
}
public static readonly DependencyProperty PushpinArrayProperty =
DependencyProperty.Register("PushpinArray", typeof(IEnumerable), typeof(BingAMapExample), new PropertyMetadata(null));
public Dictionary<int,string> MapStyleDic
{
get { return (Dictionary<int,string>)GetValue(MapStyleDicProperty); }
set { SetValue(MapStyleDicProperty, value); }
}
public static readonly DependencyProperty MapStyleDicProperty =
DependencyProperty.Register("MapStyleDic", typeof(Dictionary<int,string>), typeof(BingAMapExample), new PropertyMetadata());
public BingAMapExample()
{
InitializeComponent();
MapStyleDic = new Dictionary<int, string>();
MapStyleDic.Add(6, "卫星地图");
MapStyleDic.Add(7, "标准地图");
MapStyleDic.Add(8, "主道路名称");
var pushpins = new List<PushpinModel>();
pushpins.Add(new PushpinModel { ID = 1, Location = new Location(39.8151940395589, 116.411970893135), Title = "和义东里社区" });
pushpins.Add(new PushpinModel { ID = 2, Location = new Location(39.9094878843105, 116.33299936282), Title = "中国水科院南小区" });
pushpins.Add(new PushpinModel { ID = 3, Location = new Location(39.9219204792284, 116.203500574855), Title = "石景山山姆会员超市" });
pushpins.Add(new PushpinModel { ID = 4, Location = new Location(39.9081417418219, 116.331244439925), Title = "茂林居小区" });
PushpinArray = pushpins;
_polyLocations = new LocationCollection();
_polyLocations.Add(new Location(39.9082973053021, 116.63105019548));
_polyLocations.Add(new Location(31.9121578992881, 107.233555852083));
mapPolyline = new MapPolyline
{
Stroke = Brushes.Green,
StrokeThickness = 2,
Locations = _polyLocations,
};
CarLayer.Children.Add(mapPolyline);
carPushpin = new Pushpin
{
Template = this.Resources["CarTemplate"] as ControlTemplate,
Location = new Location(31.9121578992881, 107.233555852083),
PositionOrigin = PositionOrigin.Center,
};
CarLayer.Children.Add(carPushpin);
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(1.5);
dispatcherTimer.Tick += DispatcherTimer_Tick;
}
int index = 0;
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if (index < 0)
{
index = locations.Count - 1;
dispatcherTimer.Stop();
return;
}
carPushpin.Location = locations[index];
index--;
}
private void BtnCar_Click(object sender, RoutedEventArgs e)
{
locations = new List<Location>();
locations.Add(new Location(39.9082973053021, 116.63105019548));
locations.Add(new Location(39.0654365763652, 115.513103745601));
locations.Add(new Location(38.5861378332358, 114.897869370601));
locations.Add(new Location(38.0690298850334, 114.238689683101));
locations.Add(new Location(37.4436424646135, 113.491619370601));
locations.Add(new Location(36.8833163124675, 112.832439683101));
locations.Add(new Location(36.6015984304246, 112.480877183101));
locations.Add(new Location(36.2125510101126, 112.041424058101));
locations.Add(new Location(35.6074752751952, 111.426189683101));
locations.Add(new Location(34.9977887035825, 110.591228745601));
locations.Add(new Location(34.456028305434, 109.932049058101));
locations.Add(new Location(33.9836399832877, 109.580486558101));
locations.Add(new Location(33.5086116028286, 108.965252183101));
locations.Add(new Location(33.1046158275268, 108.525799058101));
locations.Add(new Location(32.6617655474571, 108.042400620601));
locations.Add(new Location(32.179523137361, 107.515056870601));
locations.Add(new Location(31.9121578992881, 107.233555852083));
index = locations.Count - 1;
dispatcherTimer.Start();
}
private void Map_MouseDown(object sender, MouseButtonEventArgs e)
{
var mousePosition = e.GetPosition(this);
var pinLocation = this.map.ViewportPointToLocation(mousePosition);
//Console.WriteLine(pinLocation);
}
private void Pushpin_MouseDown(object sender, MouseButtonEventArgs e)
{
var model = sender as Pushpin;
map.Center = model.Location;
map.ZoomLevel = 16;
}
private void PART_Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var grid = sender as Grid;
var model = PushpinArray.OfType<PushpinModel>().FirstOrDefault(x => x.ID.Equals(grid.Tag));
map.Center = model.Location;
map.ZoomLevel = 16;
}
private void StyleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var combobox = sender as ComboBox;
if (combobox == null) return;
var select = (int)combobox.SelectedValue;
if(aMapTitleLayer != null)
map.Children.Remove(aMapTitleLayer);
aMapTitleLayer = new AMapTitleLayer();
aMapTitleLayer.UpdateTileSourceStyle(select);
map.Children.Insert(0, aMapTitleLayer);
}
}
}
参考资料
[1]
原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers
[2]issue: https://github.com/WPFDevelopersOrg/WPFDevelopers/issues/39