最近无聊看到百度地图等,查询地点后会在地图中用气泡提示查询点的位置以及点击气泡后可进行相关信息显示以及操作,闲来无聊用ArcGIS实现了一下。目前想到的方法有两种:
(1)叠加法
将文字符号与图片符号叠加。
(2)控件法
单独封装控件通过elementlayer显示
(3)templete法
此方法和方法2有些类似,只不过通过templte属性将文字和图片写到Symbol中,然后正常通过graphicslayer渲染;
采用的技术:
arcgis for silverlight(3.1)
asp.net
此篇主要是讲方法一,方法二待有时间实践。
直接上代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Toolkit;
namespace MapMarker
{
public partial class MainPage : UserControl
{
private GraphicsLayer makerSymbolLayer;
private GraphicsLayer textSymbolLayer;
private Map myMap = null;
private InfoWindow myInfoWindow = null;
public MainPage()
{
InitializeComponent();
}
private void laodMap()
{
//Image btnImage = new Image();
//btnImage.Source = new System.Windows.Media.Imaging.BitmapImage(
// new Uri("image/mapmarker_48.png", UriKind.Relative));
//queryBtn.Content = btnImage;
Map myMap = new Map()
{
WrapAround = true,
Extent = new ESRI.ArcGIS.Client.Geometry.Envelope(-15000000, 2000000, -7000000, 8000000)
};
mapGrid.Children.Add(myMap);
this.myMap = myMap;
ArcGISTiledMapServiceLayer tileLayer = new ArcGISTiledMapServiceLayer()
{
Url = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
};
myMap.Layers.Add(tileLayer);
makerSymbolLayer = new GraphicsLayer();
textSymbolLayer = new GraphicsLayer();
myMap.Layers.Add(makerSymbolLayer);
myMap.Layers.Add(textSymbolLayer);
myInfoWindow = new InfoWindow();
myInfoWindow.Map = myMap;
mapGrid.Children.Add(myInfoWindow);
myInfoWindow.MouseLeftButtonUp+=myInfoWindow_MouseLeftButtonUp;
this.myMap.MouseClick+=myMap_MouseClick;
}
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
laodMap();
}
private void myInfoWindow_MouseLeftButtonUp(object sender, EventArgs e)
{
myInfoWindow.IsOpen = false;
}
private void myMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
{
Point screenPnt = this.myMap.MapToScreen(e.MapPoint);
GeneralTransform generalTransform = this.myMap.TransformToVisual(Application.Current.RootVisual);
Point transformScreenPnt = generalTransform.Transform(screenPnt);
IEnumerable<Graphic> selected =
this.makerSymbolLayer.FindGraphicsInHostCoordinates(transformScreenPnt);
foreach (Graphic g in selected)
{
this.myInfoWindow.Anchor = e.MapPoint;
myInfoWindow.IsOpen = true;
myInfoWindow.Content = getInfowindowContent(g.Attributes);
}
}
private void queryBtn_Click(object sender, RoutedEventArgs e)
{
Query query = new Query();
string url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5";
QueryTask queryTask = new QueryTask(url);
query.Where = "1=1";
query.ReturnGeometry = true;
query.OutSpatialReference = this.myMap.SpatialReference;
queryTask.ExecuteAsync(query);
queryTask.ExecuteCompleted+=queryTask_ExecuteCompleted;
queryTask.Failed+=queryTask_Failed;
}
private void queryTask_ExecuteCompleted(object sender, QueryEventArgs e)
{
FeatureSet fs = e.FeatureSet;
if (fs == null || fs.Features.Count == 0)
{
MessageBox.Show("未查找到任何地物");
return;
}
makerSymbolLayer.Graphics.Clear();
textSymbolLayer.Graphics.Clear();
int i=0;
Graphic newGraphic;
Graphic picGraphic;
ESRI.ArcGIS.Client.Geometry.Geometry geo;
foreach (Graphic g in fs.Features)
{
if (g.Geometry is ESRI.ArcGIS.Client.Geometry.MapPoint)
geo = g.Geometry;
else
{
geo = g.Geometry.Extent.GetCenter();
geo.SpatialReference = this.myMap.SpatialReference;
}
//新建文本符号
newGraphic = new Graphic();
newGraphic.Geometry = geo;
newGraphic.Symbol = GetTextSymbol(i);
textSymbolLayer.Graphics.Add(newGraphic);
//新建图片符号
picGraphic = new Graphic();
picGraphic.Geometry = geo;
copyAttributes(picGraphic.Attributes, g.Attributes);
picGraphic.Symbol = GetMarkSymbol();
makerSymbolLayer.Graphics.Add(picGraphic);
i++;
}
}
private void queryTask_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show(e.Error.Message);
}
private void copyAttributes(IDictionary<string, object> newAttributes, IDictionary<string, object> oldAttributes)
{
if (oldAttributes == null||newAttributes==null)
return;
newAttributes.Clear();
foreach (KeyValuePair<string, object> obj in oldAttributes)
{
newAttributes.Add(obj.Key, obj.Value);
}
}
/// <summary>
/// 获取infowindow的内容
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
private Grid getInfowindowContent(IDictionary<string, object> attributes)
{
Grid grid = new Grid();
StackPanel sp = new StackPanel();
grid.Children.Add(sp);
sp.Orientation = Orientation.Vertical;
TextBlock tb = null;
foreach (KeyValuePair<string, object> att in attributes)
{
tb = new TextBlock();
tb.Text = att.Key.ToString() + ":" + att.Value.ToString();
sp.Children.Add(tb);
}
return grid;
}
/// <summary>
/// 生成图片符号
/// </summary>
/// <returns></returns>
private PictureMarkerSymbol GetMarkSymbol()
{
PictureMarkerSymbol pictureSymbol = new PictureMarkerSymbol();
pictureSymbol.Source=new System.Windows.Media.Imaging.BitmapImage(
new Uri("image/mapmarker_48.png",UriKind.Relative));
return pictureSymbol;
}
/// <summary>
/// 生成文本符号
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private TextSymbol GetTextSymbol(int index)
{
TextSymbol textSymbol = new TextSymbol();
//偏移量计算太费劲了
textSymbol.OffsetX = -18;
textSymbol.OffsetY = -6;
//可以为其他文本,例如字母
textSymbol.Text = index.ToString();
textSymbol.FontSize = 12;
// textSymbol.Foreground = new SolidColorBrush(Colors.White);
return textSymbol;
}
}
}
界面设计
<UserControl x:Class="MapMarker.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White" Loaded="LayoutRoot_Loaded">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="toolGrid">
<Button x:Name="queryBtn" Content="查询" Height="25" Width="50" HorizontalAlignment="Left" Click="queryBtn_Click"/>
</Grid>
<Grid x:Name="mapGrid" Grid.Row="1"></Grid>
</Grid>
</UserControl>
最后,效果图
方法三
在前面已经介绍了,直接看代码:
internal static Symbol GetLocationSymbol(string imageUrl,string text)
{
MarkerSymbol rotateSymbol = new MarkerSymbol();
string template = @"<ControlTemplate
xmlns=""http://schemas.microsoft.com/client/2007""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Grid>
<Image Source=""myImageUrl"" Height=""32"" Width=""32"">
</Image>
<TextBlock Text=""mytext"" HorizontalAlignment=""Center"" VerticalAlignment=""Center"" Margin=""0,-12,0,0"" FontSize=""11"" />
</Grid>
</ControlTemplate>";
template = template.Replace("myImageUrl", imageUrl);
template = template.Replace("mytext", text);
rotateSymbol.OffsetX = 16;
rotateSymbol.OffsetY = 16;
rotateSymbol.ControlTemplate = System.Windows.Markup.XamlReader.Load(template) as ControlTemplate;
return rotateSymbol;
}
从此方法可以返回Symbol 赋值给Graphic就行了