您好,欢迎访问一九零五行业门户网

详解HTML5网络拓扑图整合OpenLayers实现GIS地图应用(图)

ht for web作为逻辑拓扑图形组件自身没有gis功能,但可以与各种gis引擎即其客户端组件进行融合,各取所长实现逻辑拓扑和物理拓扑的无缝融合,本章将具体介绍ht for web与开发免费的openlayers地图结合应用的关键技术点,该文介绍的结合的原理,其实还可推广到与arcgis、百度地图以及googlemap等众多gis地图引擎融合的解决方案。
以上抓图为本文介绍的例子最终运行效果,接下来我们一步步来实现,首选显示地图信息需要有城市经纬度数据,搜索了下感谢此篇博客提供的数据。这么大量的数据我采用的是《ht图形组件设计之道(四)》中介绍的getrawtext函数方式,有了数据之后剩下就是呈现的问题了,我们需要将ht的graphview组件与openlayers的map地图组件叠加在一起,也就是openlayers的tile地图图片在下方,graphview的组件在上方,由于graphview默认是透明的,因此非图元部分用户可穿透看到地图内容。找到合适的组件插入位置是头疼的事情,arcgis、百度地图包括googlemap几乎每个不同的gis组件都需要尝试一番才能找到合适的插入位置,其他gis引擎组件的整合以后章节再介绍,本文我们关注的openlayers的插入方式为map.viewportp.appendchild(graphview.getview())。
ht和openlayers组件叠加在一起之后,剩下就是拓扑里面图元的摆放位置与经纬度结合的问题,常规网络拓扑图中存储在ht.node图元的position是逻辑位置,和经纬度没有任何关系,因此在gis应用中我们需要根据图元的经纬度信息换算出position的屏幕逻辑坐标信息,如果你知道投影算法也可以自己提供函数处理,但所有gis组件都提供了类似的api函数供调用,当然这部分也没有标准化,不同的gis组件需要调用的api都有差异,但基本原理是一致的,对于openlayers我们通过map.getpixelfromlonlat(data.lonlat)可以将经纬度信息转换成屏幕像素逻辑坐标,也就是ht.node需要的position坐标信息。
细心的同学会想到转换是双向的,有可能用户需要拖动图元节点改变其经纬度信息,这时候我们就需要另外一个方向函数,即根据屏幕逻辑坐标转换成当前坐标对应的经纬度,在openlayers中我们通过map.getlonlatfrompixel(new openlayers.pixel(x, y));可以搞定。
显示搞定后剩下就是交互的问题了,ht自己有套交互体系,openlayers也需要地图漫游和缩放的交互,两者如何结合呢?如果能保留住两者的功能那就最好了,答案时肯定的,我们只需要添加mousedown或touchstart事件监听,如果graphview.getdataat(e)选中了图元我们就通过e.stoppropagation();停止事件的传播,这样map地图就不会响应,这时候ht接管了交互,如果没有选中图元则map接管地图操作的交互。
以上交互设计似乎很完美了,结果运行时发现了几处折腾了我很久才找到解决方案的坑:
设置map.events.fallthrough = true;否则map不会将事件透传到ht的graphview组件
graphview.getview().style.zindex = 999; 需要指定一定的zindex否则会被遮挡
graphview.getview().classname = ‘olscrollable’; 否则滚轮不会响应地图缩放
设置ht.default.basezindex: 1000 否则tooltip会被遮挡
为了让这个例子用户体验更友好,我还用心折腾了些技术点供参考:
采用开源免费的llllll.li/randomcolor/随机颜色类库,该类库还有很多非常棒的颜色获取函数,我只是简单的为每个省份显示不一样的颜色
重载了isvisible、isnotevisible和islabelvisible仅在缩放达到一定级别才显示更详细的内容,否则缩小时所有城市信息都显示完全无法查看,多少也能提高显示性能
function init(){ graphview = new ht.graph.graphview(); var view = graphview.getview(); map = new openlayers.map("map"); var ol_wms = new openlayers.layer.wms( "openlayers wms", "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: "basic"} ); map.addlayers([ol_wms]); map.addcontrol(new openlayers.control.layerswitcher()); map.zoomtomaxextent(); map.events.fallthrough = true; map.zoomtoproxy = map.zoomto; map.zoomto = function (zoom,xy){ view.style.opacity = 0; map.zoomtoproxy(zoom, xy); console.log(zoom); }; map.events.register("movestart", this, function() { }); map.events.register("move", this, function() { }); map.events.register("moveend", this, function() { view.style.opacity = 1; reset(); }); graphview.getview().classname = 'olscrollable'; graphview.setscrollbarvisible(false); graphview.setautoscrollzone(-1); graphview.handlescroll = function(){}; graphview.handlepinch = function(){}; graphview.mi(function(e){ if(e.kind === 'endmove'){ graphview.sm().each(function(data){ if(data instanceof ht.node){ var position = data.getposition(), x = position.x + graphview.tx(), y = position.y + graphview.ty(); data.lonlat = map.getlonlatfrompixel(new openlayers.pixel(x, y)); } }); } }); graphview.enabletooltip(); graphview.gettooltip = function(event){ var data = this.getdataat(event); if(data){ return '城市:' + data.s('note') + ' 经度:' + data.lonlat.lon + ' 维度:' + data.lonlat.lat; } return null; }; graphview.isvisible = function(data){ return map.zoom > 1 || this.isselected(data); }; graphview.isnotevisible = function(data){ return map.zoom > 6 || this.isselected(data); }; graphview.getlabel = function(data){ return '经度:' + data.lonlat.lon + '\n维度:' + data.lonlat.lat; }; graphview.islabelvisible = function(data){ return map.zoom > 7 || this.isselected(data); }; view.addeventlistener("ontouchend" in document ? 'touchstart' : 'mousedown', function(e){ var data = graphview.getdataat(e); if(data || e.metakey || e.ctrlkey){ e.stoppropagation(); } }, false); view.style.position = 'absolute'; view.style.top = '0'; view.style.left = '0'; view.style.right = '0'; view.style.bottom = '0'; view.style.zindex = 999; map.viewportp.appendchild(view); var color = randomcolor(); lines = china.split('\n'); for(var i=0; i<lines.length; i++) { line = lines[i].trim(); if(line.indexof('【') === 0){ //province = line.substring(1, line.length-1); color = randomcolor(); }else{ var ss = line.split(' '); if(ss.length === 3){ createnode(parsefloat(ss[1].substr(3)), parsefloat(ss[2].substr(3)), ss[0].substr(3), color); } } } } function reset(){ graphview.tx(0); graphview.ty(0); graphview.dm().each(function(data){ if(data.lonlat){ data.setposition(map.getpixelfromlonlat(data.lonlat)); } }); graphview.validate(); } function createnode(lon, lat, name, color){ var node = new ht.node(); node.s({ 'shape': 'circle', 'shape.background': color, 'note': name, 'label.background': 'rgba(255, 255, 0, 0.5)', 'select.type': 'circle' }); node.setsize(10, 10); var lonlat = new openlayers.lonlat(lon, lat); lonlat.transform('epsg:4326', map.getprojectionobject()); node.setposition(map.getpixelfromlonlat(lonlat)); node.lonlat = lonlat; graphview.dm().add(node); return node; }
以上就是详解html5网络拓扑图整合openlayers实现gis地图应用(图)的详细内容。
其它类似信息

推荐信息