Silverlight Map 技术点总结

简介: 关于Silverlight Map,很长一段时间都在学习,一边学习一边开发,总是会遇到这样、那样的问题,现在把这一年多时间里遇到的问题都整理出来,给自己积累,也希望给其他人提供帮助。 一、基于位图呈现著名的如GoogleMap,Bing Map,等等,展现在我们眼前的其实都是一小块一小块的图片,像拼图一样,在浏览器缓存里可以找到这些图,好好加以利用,还是可以有一番作为的,要问有没有专业的工具能按需下载某个区域的GoogleMap各层级图像,可以肯定的说有,但不一定好找。

关于Silverlight Map,很长一段时间都在学习,一边学习一边开发,总是会遇到这样、那样的问题,现在把这一年多时间里遇到的问题都整理出来,给自己积累,也希望给其他人提供帮助。

一、基于位图呈现
著名的如GoogleMap,Bing Map,等等,展现在我们眼前的其实都是一小块一小块的图片,像拼图一样,在浏览器缓存里可以找到这些图,好好加以利用,还是可以有一番作为的,要问有没有专业的工具能按需下载某个区域的GoogleMap各层级图像,可以肯定的说有,但不一定好找。当然,牛人都是不屑这些工具的,他们大可以自己写个,也很简单。这里提供一个现成的工具Google Map Buddy
关于效果的技术实现,GooleMap,不用多说,那早已是Ajax的一个标杆。而在Bing Map Visual Earth Map,借助了Silverlight的伟大创意,发明了诸如弹簧动画,DeepZoomMultiScaleImage等等技术,使图像的加载过程看起来更加流畅,舒适。

那么,在Silverlight中要怎样才能使用自己的地图实现这样流畅的效果呢

问题1. 流畅的图片显示过程。这一点,借助DeepZoom 软件导出数据后作为数据源交给MultiScaleImage控件实现。

问题2. DeepZoom需要一张高分辨率的地图,但分级切割后很难知晓并控制切割好的图片整体大小,只能在MultiScaleImage控件中调整,这个问题没有很好解决。

问题3. 使用MultiScaleImage 显示地图后能有流畅效果,可是怎样才能知道鼠标当前位置的相对地图坐标 这是一个转换问题。(下面说明)

问题4. 怎样在地图上能任意添加背景透明的图层,即可以理解为Canvas层,Canvas层上可以使用ItemsControls 添加任意的模板项,这些项可以是一些用户定义的小图标(如油田、机场、公交站牌、等等),当然,这些图标的地理坐标都是从数据库中读出,怎样转换成屏幕坐标并做绑定? 这也是一个转换问题。(下面说明)

问题 5. 即便解决了绑定和坐标转换,地图都是需要能放大缩小平移的,MultiScaleImage都提供了这些功能,就是说地图是没问题的,关键在于你添加的Canvas层,要与MutiScaleImage动态绑定,注意,只需要Canvas绑定,因为Canvas内部的元素都是相对坐标,会自动随Canvas变换坐标,所以可以不用考虑。
     解决这个问题的方法在于使用Silverlight提供的依赖属性功能。MultiScaleImage的主要依赖属性项有两个,ViewportOrigin,ViewportWidth ,这两个属性也是控制地图缩放的和可视位置的关键属性,将CanvasScaleTransform 值设置绑定到ViewportWidth上,当然中间需要有一个值转换器,就是实现了IValueConverter接口的转换类,用于控制缩放的两个值之间的单向转换。

问题 6. 从外部控制显示在控件中心的地图地理坐标。这也是一个坐标转换问题,大家看过GoogleEarth中是否带有输入经纬度或者地理名称,那个球就会飞到那个地方去呢,其实就是一个先缩小、再放大的过程,但是这个过程是需要一个类似反正切函数的(时间,值)变换过程。
image
幸好Silverlight 的开发工具Blend 中为我们自动生成这个曲线的动画效果。而关于中心坐标控制,则按照指定坐标与控件中心位置的偏移计算出ViewportOrgin的相对偏移量就行。

问题 7. 当一切效果显示都基本搞定时,我们就只需要数据填充了,所以接下来的问题就是数据传输,Silverlight 的数据传输不能直接使用像ADO.Net等直接数据库交互,而是只能通过Web服务或Http请求的方式获取数据,这也是客户端web应用的通用方法,如FlexJavascript 等等,那么如果只是获取数据,一般则使用WCF或者最新的.Net RIA Service技术,RIA Service 做的比较傻瓜化,基本上不需要考虑太多的问题,只要知道怎么调用就可以,WCF要自己定义数据契约,以实现用户类的可序列化,但毕竟要比WebService功能全面的多。在Silverlight客户端添加WCF服务后,会自动在Refrence.cs文件中重新生成数据契约类,方便调用(需要使用Silverlight 2+的版本在项目中添加WCF-Enable Service)。序列化过程中遇到的最常见的问题就是遇到某个类UnKnowServiceType ,在服务契约定义时加上[ServiceKnownType(typeof(用户类))]就行了。

问题 8. 使用Silverlight+WCF数据传输会遇到端口问题,典型的现象就是程序在Debug期间运行通畅,但发布到IIS上后运行就会出现错误,客户端不能获取到数据,原因就在于调试时的应用程序中服 务地址和Silverlight中保存的服务地址是相同的,而发布到IIS后,项目地址后面的端口号可能就会不一样,这时候Silverlight就找不到服务了。当然这里讨论的是非跨域访问。
解决这个问题的办法有两种
1) 修改IIS的端口,使之与调试时动态分配的端口相同
2) 修改Web项目属性,设置web选项中Servery一栏的端口设置为已经存在的IIS的端口号,调试的时候务必把IIS先关掉,否则又会自动分配。

7. 坐标问题探讨
在地图应用中,最重要的就是坐标转换问题,也是很费神的问题,所以我们忽略SRID,采用垂直坐标系,如果是自己的应用,自己的地图(这里不是指调用其他World Map来只显示自己那一小块区域,而是就是自己某个行业拍下的局部地图数据,可能是气象,地质勘测,地形地貌等等),垂直坐标系已经足够应付。如果经纬度跨度很大,应用需求对经纬度误差会造成很大影响,那就需要考虑球面投影,这时候我们也有解决的办法,CodePlex上有开源项目ProJNet,使用这个组件,可以很好的解决这个问题。SharpMap中也调用了这个库,SharpMap是基于矢量图形的后台绘制,前台位图呈现。我会在下一章中写到,这里暂不讨论。

垂直坐标转换很简单,准备一个数据类GeographicBoundBox ,包含左上角地理坐标(Ex_Longtitude,Ex_Latitude),经度跨度(LongtitudeSpread),纬度跨度(LatitudeSpread)
控件高度(ActualHeight)和宽度(ActualWidth)

那么下面就是简单的比例转换运算了:(以东经北纬为例)
每像素经度 XRate = LongtitudeSpread / ActualWidth
每像素纬度 YRate = LatitudeSpread / ActualHeight
每经度的偏移像素:1 / XRate
每纬度的偏移像素:1 / YRate
地理坐标到屏幕坐标转换
System.Windows.Point   GeographicToScreen(Coordinate c)
{  
   return new Point( ( c.X – Ex_Longtitude ) / XRate ,(Ex_Latitude – c.Y) / YRate);
}
屏幕坐标到地理坐标转换:
Coordinate   ScreenToGeographic(System.Windows.Point p)
{
   return new Coordinate((Ex_Lontitude + p.X * XRate),Ex_Latitude – p.Y * YRate);
}
要与Canvas结合起来,转换时需要利用Canvas的相对坐标属性 Canvas.TopLeft进行绑定。

关于位图的Silverlight Map 就总结到这里,诸多问题可以多多交流,下一篇将继续总结基于矢量图的Silverlight Map

目录
相关文章
|
Web App开发 JavaScript 前端开发
一起谈.NET技术,Silverlight的搜索引擎优化
  什么是SEO,为什么它是如此重要?   SEO(搜索引擎优化)是改善交通的数量和质量,从搜索引擎网站的过程。 这意味着,做搜索引擎优化您的网站将使其更具可转位及更多的人参观。 下面是你的规则应该坚持以做最好的搜索引擎优化几点: 标签应包含有关您网站的最重要的信息 最重要的内容应留在本页面(开始后标记) 所有图像标记号()应界定上的Alt标签-这是搜索引擎理解什么是图像的唯一途径说'   简短的开场白,RIA的世界   如今,网络空间是完全不同的网站。
1068 0
|
Web App开发
一起谈.NET技术,反编译Silverlight项目
  在互联网上,每天都会有很多Silverlight项目发布,有的是开源,有的只是为了展示。在Silverlight学习的初期,多数都需要模仿学习,所以,发现一个Silverlight项目,能够查看其中的源代码是最好不过了。
858 0
一起谈.NET技术,Silverlight中本地化的实现
  对于本地化这个功能我个人一直觉得在需求阶段就要确定该项目需不需要实行本地化,这样后面就可以减轻许多工作量,Sl中对本地化功能的支持与ASP.NET中一样,主要使用CultureInfo类来完成的。   下面来看实现本地化的具体流程,先来看一看我的项目结构:    这里我是把资源文件放入单独的项目中,这样结构上也比较的清晰。
887 0