我們與地圖交互的過程時刻在進行着:一個拉框放大操作,或者對地圖內容的查詢等。這些交互過程中的輸入輸出,通常都是反映在獨立於地圖數據一個“層”上。比如拉框放大,我們能看見鼠標所畫的一個矩形;又比如對興趣點的查詢,結果通常是將符合條件的興趣點的形狀高亮顯示在那個獨立的“層”中,通過它既可以反映用戶的輸入,又可以展現地圖的輸出。這個“層”就是GraphicsLayer。其實ADF開發中也有GraphicsLayer的概念,同樣在其他兩個客戶端API(JavaScript/Flex)中也能找到GraphicsLayer的身影,它們都是一樣一樣的。
本節我們主要看如何在GraphicsLayer中展現內容。當然第一個工作就是添加ESRI.ArcGIS.dll的引用,引入esri的xml命名空間;接下來在Map中添加一個GraphicsLayer圖層:
- <esri:Map x:Name="Map1">
- <esri:Map.Layers>
- <!-- 其他圖層 -->
- <esri:GraphicsLayer ID="GLayer" />
- </esri:Map.Layers>
- </esri:Map>
要讓一個Graphic顯示出來,總共分3步:
1、定義Graphic:
在xaml中
- <esri:Graphic>
- </esri:Graphic>
Graphic g= new Graphic()
2、設置Graphic的Geometry和Symbol屬性:
在xaml中
- <esri:Graphic>
- <esri:Graphic.Symbol>
- <esriSymbols:SimpleMarkerSymbol Color="Blue" Size="12" Style="Square" />
- </esri:Graphic.Symbol>
- <esriGeometry:MapPoint X="108" Y="30" />
- </esri:Graphic>
- Graphic g = new Graphic()
- {
- Geometry = new MapPoint(108, 30),
- Symbol = new SimpleMarkerSymbol()
- {
- Color = new SolidColorBrush(Colors.Blue),
- Size = 12,
- Style = SimpleMarkerSymbol.SimpleMarkerStyle.Square
- }
- };
在xaml中
- <esri:GraphicsLayer ID="GLayer">
- <esri:GraphicsLayer.Graphics>
- <esri:Graphic>
- <esri:Graphic.Symbol>
- <esriSymbols:SimpleMarkerSymbol Color="Blue" Size="12" Style="Square" />
- </esri:Graphic.Symbol>
- <esriGeometry:MapPoint X="108" Y="30" />
- </esri:Graphic>
- </esri:GraphicsLayer.Graphics>
- </esri:GraphicsLayer>
- Graphic g = new Graphic()
- {
- Geometry = new MapPoint(108, 30),
- Symbol = new SimpleMarkerSymbol()
- {
- Color = new SolidColorBrush(Colors.Blue),
- Size = 12,
- Style = SimpleMarkerSymbol.SimpleMarkerStyle.Square
- }
- };
- GraphicsLayer glayer = Map1.Layers["GLayer"] as GraphicsLayer;
- glayer.Graphics.Add(g);
圖中還有其他的圖形,無非是改變了Graphic的Geometry和Symbol屬性。圖上的那隻灰熊是一段動畫文件,利用Silverlight的特性,能夠定義出表現力豐富的各種符號。
儘管能夠完全在xaml中來完成工作,但還是建議將可視化元素的定義放在xaml中,將實現的邏輯部分放在code-behind中。看一下添加圖中那些Graphic的代碼:
- <Grid.Resources>
- <esriSymbols:SimpleMarkerSymbol x:Name="RedMarkerSymbol" Color="Red" Size="12" Style="Circle" />
- <!-- 可惜目前Silverlight只支持Jpeg和PNG格式的圖像,所以PictureMarkerSymbol無法顯示GIF格式的圖像,否則會報ImagingError的錯誤 -->
- <esriSymbolsictureMarkerSymbol x:Name="PinPictureMarkerSymbol" Source="imgs/pin.png" OffsetX="10" OffsetY="10" />
- <esriSymbols:SimpleLineSymbol x:Name="RedLineSymbol" Color="Red" Width="4" Style="Solid" />
- <esriSymbols:CartographicLineSymbol x:Name="CartoLineSymbol" Color="Red" Width="10" DashCap="Triangle" LineJoin="Round" DashArray="6,2" />
- <esriSymbols:SimpleFillSymbol x:Name="RedFillSymbol" Fill="#66FF0000" BorderBrush="Red" BorderThickness="2" />
- </Grid.Resources>
- <MediaElement x:Name="BearVideo" />
- private void AddGraphics()
- {
- GraphicsLayer glayer = Map1.Layers["GLayer"] as GraphicsLayer;
- Graphic[] graphics = new Graphic[8];
- graphics[0] = new Graphic()
- {
- Geometry = new MapPoint(108, 34),
- Symbol = RedMarkerSymbol
- };
- graphics[1] = new Graphic()
- {
- Geometry = new MapPoint(108, 30),
- Symbol = new SimpleMarkerSymbol()
- {
- Color = new SolidColorBrush(Colors.Blue),
- Size = 12,
- Style = SimpleMarkerSymbol.SimpleMarkerStyle.Square
- }
- };
- graphics[2] = new Graphic()
- {
- Geometry = new MapPoint(108, 25),
- Symbol = PinPictureMarkerSymbol
- };
- graphics[3] = new Graphic()
- {
- Geometry = new MapPoint(108, 20),
- Symbol = new TextSymbol()
- {
- FontFamily = new FontFamily("微軟雅黑, 宋體"),
- FontSize = 14,
- Foreground = new SolidColorBrush(Colors.Black),
- Text = "這是text symbol"
- }
- };
- graphics[4] = new Graphic();
- graphics[4].Symbol = RedLineSymbol;
- ESRI.ArcGIS.Geometry.PointCollection pc = new ESRI.ArcGIS.Geometry.PointCollection()
- {
- new MapPoint(95,10),
- new MapPoint(110,-15),
- new MapPoint(130,10)
- };
- ESRI.ArcGIS.Geometry.Polyline pl = new ESRI.ArcGIS.Geometry.Polyline();
- pl.Paths.Add(pc);
- graphics[4].Geometry = pl;
- graphics[5] = new Graphic();
- graphics[5].Symbol = CartoLineSymbol;
- ESRI.ArcGIS.Geometry.PointCollection pc1 = new ESRI.ArcGIS.Geometry.PointCollection()
- {
- new MapPoint(95,0),
- new MapPoint(110,-25),
- new MapPoint(130,0)
- };
- ESRI.ArcGIS.Geometry.Polyline pl1 = new ESRI.ArcGIS.Geometry.Polyline();
- pl1.Paths.Add(pc1);
- graphics[5].Geometry = pl1;
- graphics[6] = new Graphic()
- {
- Symbol = RedFillSymbol
- };
- ESRI.ArcGIS.Geometry.PointCollection pc2 = new ESRI.ArcGIS.Geometry.PointCollection()
- {
- new MapPoint(110,-30),
- new MapPoint(130,-30),
- new MapPoint(130,-45),
- new MapPoint(120,-55),
- new MapPoint(110,-45),
- new MapPoint(110,-30)
- };
- ESRI.ArcGIS.Geometry.Polygon pg = new ESRI.ArcGIS.Geometry.Polygon();
- pg.Rings.Add(pc2);
- graphics[6].Geometry=pg;
- graphics[7] = new Graphic();
- //MediaElement的Name屬性只能在xaml中定義(見幫助),所以決定了MediaElement不能完全在cs代碼中定義
- BearVideo.Source = new Uri("http://serverapps.esri.com/media/bear.wmv", UriKind.RelativeOrAbsolute);
- BearVideo.IsHitTestVisible=false;
- BearVideo.IsMuted=true;
- BearVideo.AutoPlay=true;
- BearVideo.Opacity=0;
- ESRI.ArcGIS.Geometry.Polygon pg2 = new ESRI.ArcGIS.Geometry.Polygon();
- ESRI.ArcGIS.Geometry.PointCollection pc3 = new ESRI.ArcGIS.Geometry.PointCollection()
- {
- new MapPoint(10,-20),
- new MapPoint(32,7),
- new MapPoint(62,-35),
- new MapPoint(11,-36),
- new MapPoint(10,-20)
- };
- pg2.Rings.Add(pc3);
- graphics[7].Geometry=pg2;
- graphics[7].Symbol = new SimpleFillSymbol()
- {
- Fill = new VideoBrush()
- {
- SourceName = BearVideo.Name,
- Opacity = 0.6,
- Stretch = Stretch.UniformToFill
- }
- };
- foreach (Graphic g in graphics)
- {
- glayer.Graphics.Add(g);
- g.MouseLeftButtonDown+=new MouseButtonEventHandler(graphic_MouseLeftButtonDown);
- }
- }
- private void graphic_MouseLeftButtonDown(object o,MouseButtonEventArgs e)
- {
- Graphic g=o as Graphic;
- MessageBox.Show(string.Format("Geometry:{0}\nSymbol:{1}",g.Geometry.GetType().ToString(),g.Symbol.GetType().ToString()));
- }
可以把Draw理解成一塊畫板,調用Draw的Active()方法,就可以開始在畫板上面繪畫,程序會自動記錄鼠標畫出的每個Geometry,調用DeActive()方法,停止繪畫。Active()有一個DrawMode參數,它決定了我們即將在這個畫板上畫出的內容類型:Point,Polyline,Polygon等。在畫的過程中我們可以看到地圖上可以實時反映出我們繪畫的內容,而這些則利用了Draw的預定義Symbol:DefaultMarkerSymbol,DefaultLineSymbol,DefaultPolygonSymbol等。對應關係如下:
每當完成一個圖形的繪製,就會觸發Draw.OnDrawComplete事件,利用事件參數就可以獲得Geometry,之後可以創建一個Graphic,設置一個Symbol(一般使用Draw的預定義Symbol),把畫好的這個Graphic添加到一個GraphicsLayer中。
點擊這裏,查看一個比較完整的Graphics的例子。
最後來看一下這個例子的部分代碼:
- <Grid.Resources>
- <esriSymbols:SimpleMarkerSymbol x:Name="DefaultMarkerSymbol" Color="Red" Size="12" Style="Circle" />
- <esriSymbols:CartographicLineSymbol x:Name="DefaultLineSymbol" Color="Red" Width="4" />
- <esriSymbols:SimpleFillSymbol x:Name="DefaultFillSymbol" Fill="#33FF0000" BorderBrush="Red" BorderThickness="2" />
- <esriSymbols:SimpleFillSymbol x:Name="DefaultPolygonSymbol" Fill="#33FF0000" BorderBrush="Red" BorderThickness="2" />
- </Grid.Resources>
- <esriraw x:Name="Draw1"
- DefaultRectangleSymbol="{StaticResource DefaultFillSymbol}"
- DefaultMarkerSymbol="{StaticResource DefaultMarkerSymbol}"
- DefaultLineSymbol="{StaticResource DefaultLineSymbol}"
- DefaultPolygonSymbol="{StaticResource DefaultPolygonSymbol}"
- Loaded="Draw1_Loaded"
- OnDrawComplete="Draw1_OnDrawComplete" />
- <Canvas VerticalAlignment="Top" HorizontalAlignment="Left" Margin="20,20,0,0" Width="430" Height="110">
- <Rectangle RadiusX="10" RadiusY="10" Width="430" Height="110" Fill="#98000000" Stroke="#FF6495ED" />
- <Rectangle Fill="#FFFFFFFF" Stroke="DarkGray" RadiusX="5" RadiusY="5" Canvas.Left="10" Canvas.Top="10" Width="410" Height="90" />
- <StackPanel Orientation="Vertical" Canvas.Top="5" Canvas.Left="20">
- <esriWidgets:Toolbar x:Name="ToolBar1" MaxItemHeight="80" MaxItemWidth="80" Width="380" Height="80"
- ToolbarIndexChanged="ToolBar1_ToolbarIndexChanged"
- ToolbarItemClicked="ToolBar1_ToolbarItemClicked">
- <esriWidgets:Toolbar.Items>
- <esriWidgets:ToolbarItemCollection>
- <esriWidgets:ToolbarItem Text="添加點">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/DrawPoint.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="添加折線">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/DrawPolyline.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="添加多邊形">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/DrawPolygon.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="添加矩形">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/DrawRectangle.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="添加曲線">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/DrawFreehand.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="停止添加動作">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/StopDraw.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- <esriWidgets:ToolbarItem Text="清空繪製的圖形">
- <esriWidgets:ToolbarItem.Content>
- <Image Source="imgs/eraser.png" Stretch="UniformToFill" Margin="5" />
- </esriWidgets:ToolbarItem.Content>
- </esriWidgets:ToolbarItem>
- </esriWidgets:ToolbarItemCollection>
- </esriWidgets:Toolbar.Items>
- </esriWidgets:Toolbar>
- <TextBlock x:Name="StatusTextBlock" Text="" FontWeight="Bold" HorizontalAlignment="Center"/>
- </StackPanel>
- </Canvas>
- private void Draw1_Loaded(object sender, RoutedEventArgs e)
- {
- Draw1.Map = Map1;
- }
- private void Draw1_OnDrawComplete(object sender, ESRI.ArcGIS.DrawEventArgs args)
- {
- ESRI.ArcGIS.GraphicsLayer graphicsLayer = Map1.Layers["GLayer2"] as ESRI.ArcGIS.GraphicsLayer;
- ESRI.ArcGIS.Graphic graphic = new ESRI.ArcGIS.Graphic()
- {
- Geometry = args.Geometry,
- Symbol = _activeSymbol,
- };
- graphicsLayer.Graphics.Add(graphic);
- }
- private void ToolBar1_ToolbarIndexChanged(object sender, ESRI.ArcGIS.Widgets.SelectedToolbarItemArgs e)
- {
- StatusTextBlock.Text = e.Item.Text;
- }
- private void ToolBar1_ToolbarItemClicked(object sender, ESRI.ArcGIS.Widgets.SelectedToolbarItemArgs e)
- {
- Draw1.Deactivate();
- switch (e.Index)
- {
- case 0: // Point
- Draw1.Activate(ESRI.ArcGIS.DrawMode.Point);
- _activeSymbol = strobeSymbol;
- break;
- case 1: // Polyline
- Draw1.Activate(ESRI.ArcGIS.DrawMode.Polyline);
- _activeSymbol = DefaultLineSymbol;
- break;
- case 2: // Polygon
- Draw1.Activate(ESRI.ArcGIS.DrawMode.Polygon);
- _activeSymbol = DefaultPolygonSymbol;
- break;
- case 3: // Rectangle
- Draw1.Activate(ESRI.ArcGIS.DrawMode.Rectangle);
- _activeSymbol = DefaultFillSymbol;
- break;
- case 4: // Freehand
- Draw1.Activate(ESRI.ArcGIS.DrawMode.Freehand);
- _activeSymbol = waveLineSymbol;
- break;
- case 5: // Stop Graphics
- break;
- case 6: // Clear Graphics
- ESRI.ArcGIS.GraphicsLayer graphicsLayer = Map1.Layers["GLayer2"] as ESRI.ArcGIS.GraphicsLayer;
- graphicsLayer.ClearGraphics();
- break;
- }
- }