基于SharpMap和DotNetBar的地图导航(地图缩放滑块)控件开发实践
来源:互联网 发布:梦幻手游猜拳表情源码 编辑:程序博客网 时间:2024/05/22 16:06
因工作需要,最近想开发一个网络地图下载器,在编码的过程中想到以前谷歌、百度和现在的天地图、ArcGIS里面有一个地图导航控件,就尝试着自己做了一个。其实原理也简单,上下两个按钮,中间一个可上下移动的按钮,下面按钮缩小,上面按钮放大,中间跟随移动或鼠标按住上下拖动。先上图,我做出来的效果是这样的:
这里面还有一个地方要注意,就是导航控件和地图的交互同步,缩放地图时导航控件中间的按钮要跟随上下移动,同样的操作导航控件时,地图要缩放到对应比例级别。
回到具体实现上来,如果完全使用C#自带的东西设计一个用户控件肯定会复杂一些,有没有现成的控件,只要稍微改写一下就可以呢,答案是肯定的。想到以前用第三方UI控件库DotNetBar的时候有个Slider控件,很符合我们的要求,只要继承改造一下就可以。先上完整代码,等下再来说明。
一、控件编码部分
1.控件(ZoomSlider.cs)源码:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.Linq;using System.Text;using SharpMap;using DevComponents.DotNetBar.Controls;using System.Drawing;namespace SharpMap.Forms{ /// <summary> /// 自定义地图滑块控件 /// </summary> public partial class ZoomSilder : Slider { private MapBox mapBox; private List<MapZoom> zoomList; /// <summary> /// 缩放级别 /// </summary> public List<MapZoom> ZoomList { get { return this.zoomList; } } /// <summary> /// 初始化设置 /// </summary> public ZoomSilder() { InitializeComponent(); this.DoubleBuffered = true; this.SliderOrientation = DevComponents.DotNetBar.eOrientation.Vertical; this.LabelVisible = false; this.Width = 20; this.Height = 100; } /// <summary> /// 设置背景透明 /// </summary> public void SetBackgroundTranspatent() { this.BackColor = Color.Transparent; if (this.mapBox == null) return; //这行代码很重要 this.Parent = this.mapBox; } /// <summary> /// 设置地图控件 /// </summary> /// <param name="mapBox"></param> public void SetMapControl(MapBox mapBox) { this.mapBox = mapBox; //监听地图缩放事件 this.mapBox.MapZoomChanged += new MapBox.MapZoomHandler(mapBox_MapZoomChanged); } /// <summary> /// 地图比例尺改变,滑块跟随移动 /// </summary> /// <param name="zoom"></param> void mapBox_MapZoomChanged(double zoom) { SetValueToMap(zoom); } /// <summary> /// 设置地图滑块滑动到当前地图 /// </summary> /// <param name="zoom">当前地图比例尺</param> public void SetValueToMap(double zoom) { if (this.zoomList == null || this.zoomList.Count == 0) return; this.Invoke((EventHandler)(delegate { int level = -1; if (zoom >= this.zoomList[0].Zoom) { level = this.zoomList[0].Level; } else if (zoom <= this.zoomList[this.zoomList.Count - 1].Zoom) { level = this.zoomList[this.zoomList.Count - 1].Level; } else { level = GetNearLevelByZoom(zoom); } if (level == -1) return; this.Value = level; })); } /// <summary> /// 设置比例尺 /// </summary> /// <param name="zoomList"></param> public void SetZoomList(List<MapZoom> zoomList) { this.zoomList = zoomList; if (zoomList != null && zoomList.Count != 0) { this.Minimum = zoomList[0].Level; this.Maximum = zoomList[zoomList.Count - 1].Level; this.Step = 1; } } /// <summary> /// 重写silder的valuechanged事件 /// </summary> /// <param name="e"></param> protected override void OnValueChanged(EventArgs e) { base.OnValueChanged(e); //退出条件,解决地图不能无限放大缩小的问题 if (this.mapBox == null || this.Focused == false || this.ContainsFocus == false || this.Capture == false) return; //缩放地图到地图滑块当前值对应的比例尺 double zoom = GetZoomByLevel(this.Value); if (zoom == 0.0) return; this.mapBox.Map.Zoom = zoom; this.mapBox.Refresh(); } /// <summary> /// 根据地图级别获取比例尺 /// </summary> /// <param name="level"></param> /// <returns></returns> public double GetZoomByLevel(int level) { double zoom = 0.0; if (this.zoomList == null || this.zoomList.Count == 0) return zoom; foreach (MapZoom item in this.zoomList) { if (level == item.Level) { zoom = item.Zoom; } } return zoom; } /// <summary> /// 根据地图当前比例尺获取最接近给定比例尺对应的地图缩放级别 /// </summary> /// <param name="zoom">地图当前比例尺</param> /// <returns>最接近给定比例尺的缩放级别</returns> public int GetNearLevelByZoom(double zoom) { int level = -1; if (this.mapBox == null || this.mapBox.Map == null) return level; //取最接近给定比例尺的级别 double minValue = Double.MaxValue; int minValueIndex = -1; MapZoom nearZoom = new MapZoom(); for (int i = 0; i < this.zoomList.Count - 1; i++) { if (Math.Abs(zoom - this.zoomList[i].Zoom) < minValue) { minValue = Math.Abs(zoom - this.zoomList[i].Zoom); minValueIndex = i; } } if (minValueIndex == -1) return level; level = this.zoomList[minValueIndex].Level; return level; } }}
2.地图级别、比例尺和分辨率(MapZoom.cs):
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace SharpMap.Forms{ /// <summary> /// 地图缩放级别、比例尺和分辨率 /// </summary> public class MapZoom { private int level; private double zoom; private double resolution; public MapZoom() { } public MapZoom(int level, double zoom, double resolution) { this.level = level; this.zoom = zoom; this.resolution = resolution; } /// <summary> /// 地图级别 /// </summary> public int Level { get { return this.level; } set { this.level = value; } } /// <summary> /// 比例尺 /// </summary> public double Zoom { get { return this.zoom; } set { this.zoom = value; } } /// <summary> /// 分辨率 /// </summary> public double Resolution { get { return this.resolution; } set { this.resolution = value; } } }}
二、导航控件使用
1.Form_Load事件中:
//绑定地图控件this.zoomSilder1.SetMapControl(this.mapBox1);//设置背景透明this.zoomSilder1.SetBackgroundTranspatent();
2.设置级别、比例尺和分辨率(以添加Google地图为例,AppUtils.cs):
/// <summary>/// 获取Google地图级别、比例尺和分辨率集合/// </summary>/// <returns></returns>public static List<MapZoom> GetGoogleMapZoomList(){ List<MapZoom> zoomList = new List<MapZoom>(); zoomList.Insert(0, new MapZoom(1, 295828764, 78271.51696)); zoomList.Insert(1, new MapZoom(2, 147914382, 39135.75848)); zoomList.Insert(2, new MapZoom(3, 73957191, 19567.87924)); zoomList.Insert(3, new MapZoom(4, 36978595, 9783.939621)); zoomList.Insert(4, new MapZoom(5, 18489298, 4891.96981)); zoomList.Insert(5, new MapZoom(6, 9244649, 2445.984905)); zoomList.Insert(6, new MapZoom(7, 4622324, 1222.992453)); zoomList.Insert(7, new MapZoom(8, 2311162, 611.4962263)); zoomList.Insert(8, new MapZoom(9, 1155581, 305.7481131)); zoomList.Insert(9, new MapZoom(10, 577791, 152.8740566)); zoomList.Insert(10, new MapZoom(11, 288895, 76.43702829)); zoomList.Insert(11, new MapZoom(12, 144448, 38.21851414)); zoomList.Insert(12, new MapZoom(13, 72224, 19.10925707)); zoomList.Insert(13, new MapZoom(14, 36112, 9.5546285)); zoomList.Insert(14, new MapZoom(15, 18056, 4.7773143)); zoomList.Insert(15, new MapZoom(16, 9028, 2.3886571)); zoomList.Insert(16, new MapZoom(17, 4514, 1.1943286)); zoomList.Insert(17, new MapZoom(18, 2257, 0.59716428)); zoomList.Insert(18, new MapZoom(19, 1128, 0.29858214)); return zoomList;}
3.添加到地图导航(滑块)控件:
//设置地图滑块缩放级别和比例尺等zoomSilder.SetZoomList(AppUtils.GetGoogleMapZoomList());//滑动到当前比例尺对应的级别zoomSilder.SetValueToMap(mapView.Map.Zoom);//刷新控件zoomSilder.Refresh();
最后,对几个关键的地方说明一下。
1.public void SetMapControl(MapBox mapBox),为了使地图导航控件里面能获取地图,并形成互动,必须设置一个公共的方法或属性,将地图控件传入;
2.public void SetZoomList(List<MapZoom> zoomList),传入地图级别、比例尺和分辨率,这是让导航控件动起来的前提;
3.protected override void OnValueChanged(EventArgs e),重写Slider控件的值改变事件函数,使操作导航控件,值(地图缩放级别)发生变化时,地图能够跟随缩放;
4.void mapBox_MapZoomChanged(double zoom),地图级别发生变化时,导航控件滑动到对应的值(地图级别);
5.public double GetZoomByLevel(int level),根据导航控件的当前值,获取对应的地图比例尺,这样地图控件才知道要怎么缩放;
6.public int GetNearLevelByZoom(double zoom),根据地图控件当前的比例尺,获取事先设置好的级别、比例尺和分辨率对应关系中最接近的级别。因为地图控件的当前比例尺很难和预设的吻合,而且如果限制死的话,地图控件就只能在预设的比例尺范围内缩放,这样会影响其它图层,如可无无限放大缩小的矢量数据。
最终效果大图:
- 基于SharpMap和DotNetBar的地图导航(地图缩放滑块)控件开发实践
- Flash地图控件AnyMap中的地图缩放和导航设置
- 基于百度地图开发实践
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(三):地图渲染分析
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(三):地图渲染分析
- Android开发中,集成百度地图时,如何去除地图中的比例尺控件和缩放控件
- 百度地图开发------基础地图篇------缩放空间和比例尺控件移动位置无效问题
- 基于百度地图3.1.1开发导航
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(四):地图数据访问机制分析
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(四):地图数据访问机制分析
- TurtleBot基于已知地图的自主导航
- Android 高德地图2.80新版地图开发详解(本地定位/地图显示/Mark标记/camera移动和缩放)
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
- OpenWrt 策略路由(简)
- 从0开始学习 GitHub 系列之「初识 GitHub」
- C#中的变量和常量
- reactjs+echarts绘图(二)
- URLEncoder和URLDecoder
- 基于SharpMap和DotNetBar的地图导航(地图缩放滑块)控件开发实践
- cs193p2013-2014 Assignment3
- 关于作用域链与闭包的笔记
- 357. Count Numbers with Unique Digits
- 在Ubuntu14.04_ROS_indigo上安装Kinect2驱动和bridge
- 位图的使用
- java多线程例子
- MAMP安装memcache
- 运动框架的改进