百度地图、ECharts整合HT for Web网络拓扑图应用

简介: 前一篇谈及到了ECharts整合HT for Web的网络拓扑图应用,后来在ECharts的Demo中看到了有关空气质量的相关报表应用,就想将百度地图、ECharts和HT for Web三者结合起来也做一个类似空气质量报告的报表+拓扑图应用,于是有了下面的Demo:   在这个Demo中,将GraphView拓扑图组件添加到百度地图组件中,覆盖在百度地图组件之上,并且在百度地图组件上和GraphView拓扑图组件上分别添加事件监听,相互同步经纬度和屏幕位置信息,从而来控制拓扑图上的组件位置固定在地图上,并在节点和节点之间的连线上加上了流动属性。

前一篇谈及到了ECharts整合HT for Web网络拓扑图应用,后来在EChartsDemo中看到了有关空气质量的相关报表应用,就想将百度地图、EChartsHT for Web三者结合起来也做一个类似空气质量报告的报表+拓扑图应用,于是有了下面的Demo

 

在这个Demo中,将GraphView拓扑图组件添加到百度地图组件中,覆盖在百度地图组件之上,并且在百度地图组件上和GraphView拓扑图组件上分别添加事件监听,相互同步经纬度和屏幕位置信息,从而来控制拓扑图上的组件位置固定在地图上,并在节点和节点之间的连线上加上了流动属性。右下角的图标框是采用HT for WebPanel面板组件结合ECharts图表组件完成的。

接下来我们来看看具体的代码实现:

1.百度地图是如何与HT for Web组件结合的;

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

首先需要在body中存在idmapdiv,再通过百度地图的api来创建一个map地图对象,然后创建GraphView拓扑图组件,并获取GraphView组件中的view,最后将view添加到idmapdiv的第二代孩子节点中。这时候问题就来了,为什么要将view添加到map的第二代孩子节点中呢,当你审查元素时你会发现这个div是百度地图的遮罩层,将view添加到上面,会使view会是在地图的顶层可见,不会被地图所遮挡。

2.百度地图和GraphView的事件监听;

map.addEventListener('moveend', function(e){
   resetPosition();
});
map.addEventListener('dragend', function(e){
   resetPosition();
});                                
map.addEventListener('zoomend', function(e){
	resetPosition();
});

graphView.handleScroll = function(){};
graphView.handlePinch = function(){};

function resetPosition(e){
	graphView.tx(0);
	graphView.ty(0);
	dataModel.each(function(data){
		var lonLat, position;
		if(data instanceof ht.HtmlNode){
			if(data.getId() != 'chartTotal') {
				position = data.getHost().getPosition();
				position = {x: position.x + 168, y: position.y + 158};
				data.setPosition(position.x, position.y);
			}
		} else if(data instanceof ht.Node){
			lonLat = data.lonLat;
			position = map.pointToPixel(lonLat);
			data.setPosition(position.x,position.y);
		}
	});
}

首先监听map的三个事件:moveend dragend zoomend,这三个事件做了同一件事--修改DataModel中所有dataposition属性,让其在屏幕上的坐标与地图同步,然后将GraphViewScrollPinch两个事件的执行函数设置为空函数,就是当监听到Scroll或者Pinch事件时不做任何的处理,将这两个事件交给map来处理。

resetPosition函数中,做的事情很简单:遍历DataModel中的data,根据它们各自在地图上的经纬度来换算成屏幕坐标,并将坐标设置到相应的data中,从而达到GraphView中的节点能够固定在地图上的效果。

3.创建右下角的图表组件:

ht.Chart = function(option){
	var self = this,
			view = self._view = document.createElement('div');
	view.style.position = 'absolute';
	view.style.setProperty('box-sizing', 'border-box', null);
	self._option = option;
	self._chart = echarts.init(self.getView());
	if(option)
		self._chart.setOption(option);
	self._FIRST = true;
};
ht.Default.def('ht.Chart', Object, {
	ms_v: 1,
	ms_fire: 1,
	ms_ac: ['chart', 'option', 'isFirst', 'view'],
	validateImpl: function(){
		var self = this,
				chart = self._chart;
		chart.resize();
		if(self._FIRST){
			self._FIRST = false;
			chart.restore();
		}
	},
	setSize: function(w, h){
		var view = this._view;
		view.style.width = w + 'px';
		view.style.height = h + 'px';
	}
});

function createPanel(title, width, height){
	chart = new ht.Chart(option);
	var c = chart.getChart();
	c.on(echarts.config.EVENT.LEGEND_SELECTED, legendSelectedFun);
	var chartPanel = new ht.widget.Panel({
		title: title,
		restoreToolTip: "Overview",
		width: width,
		contentHeight: height,
		narrowWhenCollapse: true,
		content: chart,
		expanded: true
	});
	chartPanel.setPositionRelativeTo("rightBottom");
	chartPanel.setPosition(0, 0);
	chartPanel.getView().style.margin = '10px';

	document.body.appendChild(chartPanel.getView());
}

首先定义了ht.Chart类,并实现了validateImpl方法,方法中处理的逻辑也很简单:在每次方法执行的时候调用图表的reset方法重新设定图标的展示大小,如果该方法是第一次执行的话,就调用图表的restore方法将图表还原为最原始的状态。会有这样的设计是因为ht.Chart类中的view是动态创建的,在没有添加到dom之前将一直存在于内存中,在内存中因为并没有浏览器宽高信息,所以div的实际宽高均为0,因此chartoption内容绘制在宽高为0div中,即使你resizechart,如果没用重置图表状态的话,图表状态将无法在图表上正常显示。

接下来就是创建panel图表组件了,这是HT for WebPanel组件的基本用法,其中content属性的值可以是HT for Web的任何组件或div元素,如果是HT fro Web组件的话,该组件必须实现了validateImpl方法,因为在panel的属性变化后将会调用content对应组件的validateImpl方法来重新布局组件内容。

4.EChartsGraphView拓扑图组件的交互:

legendSelectedFun = function(param) {
	if(chart._legendSelect){
		delete chart._legendSelect;
		return;
	}
	console.info(param);
	var id = nodeMap[param.target],
			dm = graphView.dm(),
			data = dm.getDataById(id),
			sm = dm.sm(),
			selection = sm.getSelection();

	if(param.selected[param.target]) {
		sm.appendSelection([data]);
		if(selectionData.indexOf(param.target) < 0){
			selectionData.push(param.target);
		}
	}else {
		sm.removeSelection([data]);
		var index = selectionData.indexOf(param.target);
		if(index >= 0){
			selectionData.splice(index, 1);
		}
	}
	sm.setSelection(selection.toArray());
};

graphView.mi(function(e){
	console.info(e.kind, e.data);
	var c = chart.getChart(),
			legend = c.component.legend,
			selectedMap = legend.getSelectedMap();

	if(e.kind === 'endRectSelect'){
		chart._legendSelect = true;
		for(var name in notes){
			legend.setSelected(name, false);
		}
		notes = {};
		graphView.dm().sm().each(function(data){
			var note = data.s('note');
			if(note)
				notes[note] = 1;
		});
		for(var name in notes){
			legend.setSelected(name, true);
		}
	} else if(e.kind === 'clickData'){
		chart._legendSelect = true;
		var data = e.data;
		if(data instanceof ht.Node){
			var note = data.s('note');

			if(note){
				var selected = legend.isSelected(note);
				if(selected){
					graphView.dm().sm().removeSelection([data]);
				}
				legend.setSelected(note, !selected);
			}
		}
	}
});

legendSelectedFun函数是EChart图表的legend插件选中事件监听,其中处理的逻辑是:当legend插件中的某个节点被选中了,也选中在GraphView拓扑图中对应的节点,当取消选中是,也取消选中GraphView拓扑图中对应的节点。

GraphView中添加交互监听,如果在GraphView中做了框选操作,在框选结束后,将原本legend插件上被选中的节点取消选中,然后再获取被选中节点,并在legend插件上选中对应节点;当GraphView上的节点被选中,则根据legend插件中对应节点选中情况来决定legend插件中的节点和graphView上的节点是否选中。

GraphView交互中,我往chart实例中添加了_legendSelect变量,该变量的设定是为了阻止在GraphView交互中修改legend插件的节点属性后回调legendSelectedFun回调函数做修改GraphView中节点属性操作。

今天就写到这吧,希望这篇文章能够帮到那些有地图、拓扑图、图表相结合需求的朋友,在设计上可能想法还不够成熟,希望大家不吝赐教。

目录
相关文章
|
11月前
|
机器学习/深度学习 PyTorch TensorFlow
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic,深度学习探索者。深耕TensorFlow与PyTorch,分享框架对比、性能优化与实战经验,助力技术进阶。
|
监控 安全 Shell
管道符在渗透测试与网络安全中的全面应用指南
管道符是渗透测试与网络安全中的关键工具,既可用于高效系统管理,也可能被攻击者利用实施命令注入、权限提升、数据外泄等攻击。本文全面解析管道符的基础原理、实战应用与防御策略,涵盖Windows与Linux系统差异、攻击技术示例及检测手段,帮助安全人员掌握其利用方式与防护措施,提升系统安全性。
556 6
|
12月前
|
机器学习/深度学习 人工智能 算法
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic带你深入卷积神经网络(CNN)核心技术,从生物启发到数学原理,详解ResNet、注意力机制与模型优化,探索视觉智能的演进之路。
958 11
|
数据采集 存储 数据可视化
Python网络爬虫在环境保护中的应用:污染源监测数据抓取与分析
在环保领域,数据是决策基础,但分散在多个平台,获取困难。Python网络爬虫技术灵活高效,可自动化抓取空气质量、水质、污染源等数据,实现多平台整合、实时更新、结构化存储与异常预警。本文详解爬虫实战应用,涵盖技术选型、代码实现、反爬策略与数据分析,助力环保数据高效利用。
669 0
|
11月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
748 4
|
缓存 JavaScript 前端开发
鸿蒙5开发宝藏案例分享---Web开发优化案例分享
本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
|
JavaScript 前端开发 API
鸿蒙5开发宝藏案例分享---Web加载时延优化解析
本文深入解析了鸿蒙开发中Web加载完成时延的优化技巧,结合官方案例与实际代码,助你提升性能。核心内容包括:使用DevEco Profiler和DevTools定位瓶颈、四大优化方向(资源合并、接口预取、图片懒加载、任务拆解)及高频手段总结。同时提供性能优化黄金准则,如首屏资源控制在300KB内、关键接口响应≤200ms等,帮助开发者实现丝般流畅体验。
|
前端开发 JavaScript Shell
鸿蒙5开发宝藏案例分享---Web页面内点击响应时延分析
本文为鸿蒙开发者整理了Web性能优化的实战案例解析,结合官方文档深度扩展。内容涵盖点击响应时延核心指标(≤100ms)、性能分析工具链(如DevTools时间线、ArkUI Trace抓取)以及高频优化场景,包括递归函数优化、网络请求阻塞解决方案和setTimeout滥用问题等。同时提供进阶技巧,如首帧加速、透明动画陷阱规避及Web组件初始化加速,并通过优化前后Trace对比展示成果。最后总结了快速定位问题的方法与开发建议,助力开发者提升Web应用性能。
|
JSON 开发框架 自然语言处理
【HarmonyOS Next之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(三)
本文主要介绍了应用开发中的三大核心内容:生命周期管理、资源限定与访问以及多语言支持。在生命周期部分,详细说明了应用和页面的生命周期函数及其触发时机,帮助开发者更好地掌控应用状态变化。资源限定与访问章节,则聚焦于资源限定词的定义、命名规则及匹配逻辑,并阐述了如何通过 `$r` 引用 JS 模块内的资源。最后,多语言支持部分讲解了如何通过 JSON 文件定义多语言资源,使用 `$t` 和 `$tc` 方法实现简单格式化与单复数格式化,为全球化应用提供便利。
444 104
|
JavaScript 前端开发 API
【HarmonyOS Next之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(二)
本文介绍了HarmonyOS应用开发中的HML、CSS和JS语法。HML作为标记语言,支持数据绑定、事件处理、列表渲染等功能;CSS用于样式定义,涵盖尺寸单位、样式导入、选择器及伪类等特性;JS实现业务逻辑,包括ES6语法支持、对象属性、数据方法及事件处理。通过具体代码示例,详细解析了页面构建与交互的实现方式,为开发者提供全面的技术指导。
678 104

热门文章

最新文章