在前面《百度地图、ECharts整合HT for Web网络拓扑图应用》我们有介绍百度地图和 HT for Web 的整合,我们今天来谈谈 OpenLayers 和 HT for Web 的整合。

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.viewPortDiv.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接管地图操作的交互。

以上交互设计似乎很完美了,结果运行时发现了几处折腾了我很久才找到解决方案的坑:

  1. 设置map.events.fallThrough = true;否则map不会将事件透传到HT的GraphView组件
  2. graphView.getView().style.zIndex = 999; 需要指定一定的zIndex否则会被遮挡
  3. graphView.getView().className = ‘olScrollable’; 否则滚轮不会响应地图缩放
  4. 设置ht.Default.baseZIndex: 1000 否则ToolTip会被遮挡

为了让这个例子用户体验更友好,我还用心折腾了些技术点供参考:

  1. 采用开源免费的http://llllll.li/randomColor/随机颜色类库,该类库还有很多非常棒的颜色获取函数,我只是简单的为每个省份显示不一样的颜色
  2. 重载了isVisible、isNoteVisible和isLabelVisible仅在缩放达到一定级别才显示更详细的内容,否则缩小时所有城市信息都显示完全无法查看,多少也能提高显示性能

以下为最终效果的抓图、视频和源代码:http://v.youku.com/v_show/id_XODM5Njk0NTU2.html

   

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.viewPortDiv.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 地图应用相关推荐

  1. echarts力导向图节点连线动画_基于 HTML5 网络拓扑图的快速开发之入门篇(一)...

    前言 计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构.网络的拓 ...

  2. html5的网络拓扑图,基于 HTML5 网络拓扑图的快速开发之入门篇(一)

    前言 计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构.网络的拓 ...

  3. 前端入门:快速开发基于 HTML5 网络拓扑图应用

    计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构.网络的拓扑结构 ...

  4. 快速开发基于 HTML5 网络拓扑图应用--入门篇(一)

    2019独角兽企业重金招聘Python工程师标准>>> 计算机网络的拓扑结构是引用拓扑学中研究与大小,形状无关的点.线关系的方法.把网络中的计算机和通信设备抽象为一个点,把传输介质抽 ...

  5. 快速开发基于 HTML5 网络拓扑图应用--入门篇(二)

    上一篇我们绘制了一个 graphView 场景,在场景之上通过 graphView.dm() 获取数据容器,并通过 graphView.dm().add() 函数添加了两个 Node 节点,并通过 s ...

  6. 基于 HTML5 网络拓扑图的快速开发之入门篇(二)

    2019独角兽企业重金招聘Python工程师标准>>> 前言 上一篇我们绘制了一个 graphView 场景,在场景之上通过 graphView.dm() 获取数据容器,并通过 gr ...

  7. 快速开发基于 HTML5 网络拓扑图应用之 DataBinding 数据绑定篇

    前言 发现大家对于我从 json 文件中直接操作节点属性来控制界面的动态变化感到比较好奇,所以这篇就针对数据绑定以及如何使用这些绑定的数据做一篇说明,我写了一个简单的例子,基于机房工控的服务器上设备的 ...

  8. HTML5第三弹:亦酷亦萌的网络拓扑图

    前言 前一篇3D机房好像有点火,看来轻量的Web 3D是大势所趋,当时选择WebGL而不是U3D真是灰常英明的抉择. 3D虽然炫酷,但在真正的企业应用里,数据.关系的呈现还是要回到传统2D界面,而HT ...

  9. 基于 HTML5 Canvas 绘制的电信网络拓扑图

    电信网结构(telecommunication network structure)是指电信网各种网路单元按技术要求和经济原则进行组合配置的组合逻辑和配置形式.组合逻辑描述网路功能的体系结构,配置形式 ...

最新文章

  1. js long类型精度丢失_浮点数丢失精度
  2. SVM中为何间隔边界的值为正负1
  3. Oracle中Null与空字符串' '的区别
  4. Hbase(1)——基础语句(1)
  5. mysql 表 地图_报表中的地图怎么做?
  6. Java和Round-Robin上的AtomicInteger
  7. 类的初始化和实例的初始化
  8. python中的单例模式_Python单例模式
  9. harbor 多端口_总结—Harbor仓库部署和使用问题集锦
  10. UE4 下载安装操作步骤
  11. Windows设置防火墙允许指定应用正常使用网络
  12. Thinkpad T470 内置电池问题
  13. 将assets文件转为byte[]
  14. 如何让自己的博客被搜索引擎收录
  15. 服务器虚拟化专用ovf模板,开放虚拟化格式(OVF)
  16. 输出两个数之间的水仙花数C++
  17. 分享6款好用并免费的远程管理工具
  18. BPI-M1P(全志A20)刷Android启动卡之后启动的过程
  19. MATLAB中的impixel函数——获取图像像素值
  20. 不使用Ultra Liberarion软件导出BXL文件的方法

热门文章

  1. cmakelist基本语法
  2. 最安全的门禁系统来了,贝迪特掌静脉引领“刷手进门”新浪潮
  3. android 耳机 音量调节 id,Android音频相关(一)插入耳机后调节音量(安全音量)...
  4. 单片机led流水灯实验c语言程序,单片机LED流水灯实验及流程图源代码详解
  5. 思科路由器重置密码的方法
  6. 【SQL时间截取】数据库Sql实现截取时间段和日期
  7. ajax的主要核心对象,简单谈谈AJAX核心对象
  8. (拿走不谢)H5微信分享时,在苹果手机分享一直不行,公开微信分享完整工具,以及微信地图
  9. 怎么测试才能测全面?我有 5 点和你分享
  10. uniapp系列-改变底部安全区-顶部的手机信号、时间、电池栏颜色样式