百度地图与HT for Web结合的GIS网络拓扑应用

简介: 在《HT for Web整合OpenLayers实现GIS地图应用》篇中介绍了HT for Web与OpenLayers的整合,不少朋友反应国内用得比较多的还是百度地图,虽然HT整合百度地图原理与OpenLayers一致,但不同GIS引擎客户端结合代码细节还是有不少差异,自定义地图风格更是完全不一样,为此我再开篇介绍下HT与百度地图整合的方案,这次我们将改进以前的例子,除了代表城市的拓扑节点外,再增加连线连接省会和城市,实现网络拓扑链路的流动效果。

在《HT for Web整合OpenLayers实现GIS地图应用》篇中介绍了HT for Web与OpenLayers的整合,不少朋友反应国内用得比较多的还是百度地图,虽然HT整合百度地图原理与OpenLayers一致,但不同GIS引擎客户端结合代码细节还是有不少差异,自定义地图风格更是完全不一样,为此我再开篇介绍下HT与百度地图整合的方案,这次我们将改进以前的例子,除了代表城市的拓扑节点外,再增加连线连接省会和城市,实现网络拓扑链路的流动效果。

Screen Shot 2014-12-03 at 11.43.05 PMScreen Shot 2014-12-03 at 11.18.02 PMScreen Shot 2014-12-03 at 11.16.55 PM

百度地图有多种客户端SDK,我们这里用的自然是JavaScript版的API,百度地图的2.0版增加了不少新功能,例如可以自定义地图样式模板,本例中我们特意设置成style:’midnight’的深色背景风格。插入map的位置与OpenLayers也不一样,通过mapDiv.firstChild.firstChild.appendChild(view);插入,zIndex这些属性都还好不需要设置。

坐标转换方面从经纬度转换成平面坐标是map.pointToPixel函数,通过node.setPosition(map.pointToPixel(new BMap.Point(lon, lat)));可设置ht.Node对应的平面逻辑坐标,通过map.pixelToPoint(new BMap.Pixel(x,y))可将平面坐标转换成经纬度坐标,我们在监听节点图元被拖拽结束的endMove需要重新计算当前位置的经纬度时用到。

地图数据方面每个省的省会城市都是第一个出现,因此我们构建了size大一点的带渐进色的图元代表省会城市,其他城市构建时同时构建ht.Edge的连线与省会节点连接,同时引入HTht-flow.js插件,只需要graphView.enableFlow(60);一句话就可以启动流动连线功能,每条edge连线还可以有很多flow.*相关的流动参考可控制流动效果,这里的简单例子我们不需要做定制,保持HT默认的流动参数就足够酷了。

另外通过graphView.setLayers(['edgeLayer', 'nodeLayer']);我们为拓扑设置了两个层,node.setLayer(‘nodeLayer’);和edge.setLayer(‘edgeLayer’)使得图元节点全部呈现于连线之上,从这个细节大家可以发现,以前需要在GIS的SDK扩展的功能也可以通过在HTGraphView实现,地图仅仅是作为背景,业务逻辑代码完全在更灵活强大的HT模型中进行。

其他方面细节还由监听map的缩放等操作对拓扑图元重新定位,以及监听交互决定GraphView还是Map进行控制等都与以前的文章类似,这里就不再介绍了,以下为操作视频、抓图和源代码供大家参考,这样的结合可完美的将百度地图丰富的地图数据信息,与HT强大的逻辑拓扑功能相结合,否则光靠百度地图SDK的API的扩展方式,用户只能做些简单的效果,例如连线流动等效果都远不如HT这样一行代码就搞定来的容易。http://v.youku.com/v_show/id_XODQxMDcwNjQ0.html

Screen Shot 2014-12-03 at 11.12.43 PM

Screen Shot 2014-12-03 at 9.43.40 PMScreen Shot 2014-12-04 at 12.31.13 AM

var dataModel = new ht.DataModel();
var graphView = new ht.graph.GraphView(dataModel);              
var map = null;   

function init() {
    map = new BMap.Map("map");   
    var point = new BMap.Point(116.404, 39.915);                          
    map.addTileLayer(new BMap.TrafficLayer());                    
    map.centerAndZoom(point, 4);                    
    map.enableScrollWheelZoom();                       
    map.addControl(new BMap.NavigationControl());                               

    map.setMapStyle({
        features: ["road", "building","water","land"],
        style:'midnight'
    });

    var view = graphView.getView();
    view.className = 'graphView'; 
    var mapDiv = document.getElementById('map');
    mapDiv.firstChild.firstChild.appendChild(view);

    map.addEventListener('movestart', function(e){                   
       view.style.opacity = 0;
    });
    map.addEventListener('moveend', function(e){
       view.style.opacity = 1; 
       resetPosition(); 
    });
    map.addEventListener('dragstart', function(e){
       view.style.opacity = 0;                
    });
    map.addEventListener('dragend', function(e){
       view.style.opacity = 1; 
       resetPosition(); 
    });                                
    map.addEventListener('zoomstart', function(e){
        view.style.opacity = 0;
    });                
    map.addEventListener('zoomend', function(e){
        view.style.opacity = 1;    
        resetPosition(); 
    });                

    graphView.setLayers(['edgeLayer', 'nodeLayer']);
    graphView.enableFlow(60);
    graphView.enableToolTip();
    graphView.getToolTip = function(event){
        var data = this.getDataAt(event);
        if(data instanceof ht.Node){
            return '城市:' + data.s('note') + '
经度:' + data.lonLat.lng + '
维度:' + data.lonLat.lat;
        }
        return null;
    };
    graphView.isVisible = function(data){
        return map.getZoom() > 1 || this.isSelected(data);
    };
    graphView.isNoteVisible = function(data){
        return map.getZoom() > 8 || this.isSelected(data);
    }; 
    graphView.getLabel = function(data){
        if(data instanceof ht.Node){
            return '经度:' + data.lonLat.lng + '\n维度:' + data.lonLat.lat;
        }                    
    };
    graphView.isLabelVisible = function(data){
        return map.getZoom() > 9 || this.isSelected(data);
    }; 

    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.pixelToPoint(new BMap.Pixel(x,y)); 
                }                            
            });
        }
    });

    graphView.setAutoScrollZone(-1);
    graphView.handleScroll = function(){};
    graphView.handlePinch = function(){};

    var handleClick = function(e){
        var data = graphView.getDataAt(e);
        if(data){
            e.stopPropagation();
        }
        else if(e.metaKey || e.ctrlKey){
            e.stopPropagation();
        }
    };
    graphView.getView().addEventListener('click', handleClick, false);                
    graphView.getView().addEventListener('dblclick', handleClick, false);
    graphView.getView().addEventListener(ht.Default.isTouchable ? 'touchstart' : 'mousedown', handleClick, false);

    window.addEventListener("resize", function(e) {
        graphView.invalidate();
    }, false);                 

    var color = randomColor(),
        province = null;
    lines = china.split('\n');
    for(var i=0; i<lines.length; i++) {
        line = lines[i].trim();
        if(line.indexOf('【') === 0){               
            color = randomColor();
            province = null;
        }else{
            var ss = line.split(' ');
            if(ss.length === 3){
                var node = createNode(parseFloat(ss[1].substr(3)), parseFloat(ss[2].substr(3)), ss[0].substr(3), color); 
                if(province){
                    var edge = new ht.Edge(province, node);
                    edge.s({
                        'edge.center': true,
                        'edge.width': 1,                                    
                        'flow': true
                    });
                    edge.setLayer('edgeLayer');
                    dataModel.add(edge);
                }else{
                    province = node;
                    node.s({                                   
                        'shape.gradient': 'radial.center',                                    
                        'border.type': 'circle',
                        'border.width': 1,
                        'border.color': 'rgba(200, 200, 200, 0.5)'                                    
                    });
                    node.setSize(15, 15);
                }
            }
        }
    }                

}

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.setLayer('nodeLayer');
    node.setSize(10, 10);
    var lonLat = new BMap.Point(lon, lat); 
    node.setPosition(map.pointToPixel(lonLat));
    node.lonLat = lonLat;
    graphView.dm().add(node);
    return node;
}            

function resetPosition(e){
    graphView.tx(0);
    graphView.ty(0);
    dataModel.each(function(data){
        if(data instanceof ht.Node){
            var lonLat = data.lonLat,
                position = map.pointToPixel(lonLat);   
            data.setPosition(position.x,position.y);                           
        }
    });            
}

 

目录
相关文章
|
3天前
|
前端开发 安全 JavaScript
构建高效Web应用:前后端分离架构的实践
【9月更文挑战第4天】在数字时代,Web应用已成为企业与用户互动的主要平台。本文将介绍如何通过前后端分离的架构设计来构建高效的Web应用,探讨该架构的优势,并分享实现过程中的关键步骤和注意事项。文章旨在为开发者提供一种清晰、高效的开发模式,帮助其在快速变化的市场环境中保持竞争力。
|
7天前
|
中间件 编译器 数据处理
在web开发中应用管道过滤器
【9月更文挑战第1天】本文介绍管道-过滤器架构将数据处理流程分解为一系列独立组件,通过管道连接,适用于数据流处理如图像处理、编译器设计等。通过具体实例说明了Gin如何有效支持管道-过滤器风格的设计,构建高性能Web服务。
26 9
|
8天前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
18 1
|
8天前
|
Rust 安全 开发者
惊爆!Xamarin 携手机器学习,开启智能应用新纪元,个性化体验与跨平台优势完美融合大揭秘!
【8月更文挑战第31天】随着互联网的发展,Web应用对性能和安全性要求不断提高。Rust凭借卓越的性能、内存安全及丰富生态,成为构建高性能Web服务器的理想选择。本文通过一个简单示例,展示如何使用Rust和Actix-web框架搭建基本Web服务器,从创建项目到运行服务器全程指导,帮助读者领略Rust在Web后端开发中的强大能力。通过实践,读者可以体验到Rust在性能和安全性方面的优势,以及其在Web开发领域的巨大潜力。
18 0
|
8天前
|
开发者 Java 前端开发
Struts 2验证框架:如何让数据校验成为Web开发的隐形守护者?揭秘前后端一致性的秘诀
【8月更文挑战第31天】在现代Web开发中,数据验证对确保应用健壮性和良好用户体验至关重要。随着前后端分离架构的普及,保证数据校验一致性尤为关键。Struts 2 验证框架基于 JavaBean 验证 API(JSR 303/JSR 380),允许开发者通过注解或 XML 配置轻松定义验证规则,确保输入数据在执行业务逻辑前已通过验证。此外,Struts 2 支持与前端 JavaScript 验证相结合,确保前后端数据校验一致,提升用户体验。通过注解、XML 配置和资源文件,开发者可以轻松定义和调整验证规则,实现前后端一致的数据校验,提高应用健壮性。
18 0
|
8天前
|
Java 缓存 数据库连接
揭秘!Struts 2性能翻倍的秘诀:不可思议的优化技巧大公开
【8月更文挑战第31天】《Struts 2性能优化技巧》介绍了提升Struts 2 Web应用响应速度的关键策略,包括减少配置开销、优化Action处理、合理使用拦截器、精简标签库使用、改进数据访问方式、利用缓存机制以及浏览器与网络层面的优化。通过实施这些技巧,如懒加载配置、异步请求处理、高效数据库连接管理和启用GZIP压缩等,可显著提高应用性能,为用户提供更快的体验。性能优化需根据实际场景持续调整。
30 0
|
8天前
|
Java 数据库连接 Spring
Struts 2 插件开发竟如魔法盛宴,为框架注入超能力,开启奇幻编程之旅!
【8月更文挑战第31天】在Web开发中,Struts 2插件开发允许我们在不改动框架核心代码的前提下,通过创建实现特定接口的Java类来扩展框架功能、调整其行为或促进与其他框架(如Spring、Hibernate)的集成,从而更好地满足特定业务需求。遵循良好的设计原则与实践,能够确保插件的高效稳定运行并提升整体项目的可维护性。具体步骤包括创建项目、定义插件类、实现初始化与销毁逻辑,并将插件部署至应用中。
29 0
|
8天前
|
开发者 Java 开发框架
JSF与EJB,打造企业级应用的神器!让你的Web应用更加稳定、高效!
【8月更文挑战第31天】在现代企业级应用开发中,JSF(JavaServer Faces)与EJB(Enterprise JavaBeans)是两大核心技术。JSF作为一款基于Java的Web应用框架,以其丰富的UI组件和表单处理功能著称;EJB则专注于提供分布式事务处理及远程调用等企业级服务。两者的结合为企业应用带来了高效便捷的开发模式。下文将通过一个简单的示例展示如何利用JSF进行用户信息的输入与保存,并借助EJB实现相关业务逻辑。尽管这一组合具有明显优势,但在实际应用中还需考虑其局限性并作出合理选择。
20 0
|
8天前
|
开发者 安全 SQL
JSF安全卫士:打造铜墙铁壁,抵御Web攻击的钢铁防线!
【8月更文挑战第31天】在构建Web应用时,安全性至关重要。JavaServer Faces (JSF)作为流行的Java Web框架,需防范如XSS、CSRF及SQL注入等攻击。本文详细介绍了如何在JSF应用中实施安全措施,包括严格验证用户输入、使用安全编码实践、实施内容安全策略(CSP)及使用CSRF tokens等。通过示例代码和最佳实践,帮助开发者构建更安全的应用,保护用户数据和系统资源。
19 0
|
8天前
|
开发者 前端开发 开发框架
JSF与移动应用,开启全新交互体验!让你的Web应用轻松征服移动设备,让用户爱不释手!
【8月更文挑战第31天】在现代Web应用开发中,移动设备的普及使得构建移动友好的应用变得至关重要。尽管JSF(JavaServer Faces)主要用于Web应用开发,但结合Bootstrap等前端框架,也能实现优秀的移动交互体验。本文探讨如何在JSF应用中实现移动友好性,并通过示例代码展示具体实现方法。使用Bootstrap的响应式布局和组件可以确保JSF页面在移动设备上自适应,并提供友好的表单输入和提交体验。尽管JSF存在组件库较小和学习成本较高等局限性,但合理利用其特性仍能显著提升用户体验。通过不断学习和实践,开发者可以更好地掌握JSF应用的移动友好性,为Web应用开发贡献力量。
16 0