现在我要实现一个监控功能,其效果如下图:
云南省下面的各个市州向昆明市上报一些数据,要达到这种效果其实还是很方便的。具体实现过程如下:数据交换监控图为云南省下面的各个市州向昆明市上报一些数据,要达到这种效果其实还是很方便的。具体实现过程如下:
定义绘图区域
这一步很简单,只需要一个canvas绘图区即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>数据交换监控</title>
<style type="text/css">
body {
margin: auto
}
</style>
</head>
<script src="source/jquery-1.7.2.js"></script>
<body>
<div id="map" style="width:600px;height:600px;margin: auto"></div>
<script src="source/echarts.js"></script>
<script src="source/data.js"></script>
<script src="source/hashmap.js"></script>
<script src="map.js"></script>
</body>
</html>
需要注意的是,map这个div的尺寸要设置成等边的。否则最终显示的地图会被挤压。原因是canvas的尺寸就是这个DIV样式的高度和宽度。
引入相关库
在上面文件里引入了相关的库:jquery,echarts。hashmap.js为js的版本的HashMap实现。map.js为我们的数据展示逻辑代码。data.js为数据上报展示效果的数据源,其结构如下:
//上报数据的城市,其name对应geo地图数据中的properties数组元素的name
var dataSource = [{
dataSourceId: 2018,
data: [
{
name: '文山壮族苗族自治州',
value: 10
},
{
name: '怒江傈僳族自治州',
value: 20
},
{
name: '西双版纳傣族自治州',
value: 20
},
{
name: '大理白族自治州',
value: 10
},
{
name: '楚雄彝族自治州',
value: 20
},
{
name: '曲靖市',
value: 1
}]
},
{
dataSourceId: 2017,
data: [
{
name: '文山壮族苗族自治州',
value: 90
}
]
}];
//中心汇入点城市
var center = '昆明市';
初始化echarts
我们采用require来按需加载echarts所需的图标组件,具体的代码在map.js:
/**
* 模拟迁徙图功能实现
*/
require.config({
paths: {
echarts: './source'
}
});
var ecConfig;
require(
[
'echarts',
'echarts/chart/map'
],
function (ec) {
ecConfig = require('echarts/config');
myChart = ec.init(document.getElementById('map'));
initData();
loadAll(2018, '数据交换监控');
}
);
var myChart;
option = {
backgroundColor: '#1b1b1b',
color: ['gold', 'aqua', 'lime'],
title: {
show: true,
text: ' ',
x: 'center',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item',
formatter: function (params, ticket, callback) {
/*$.get('detail?name=' params.name, function (content) {
callback(ticket, toHTML(content));
});*/
var tips = '<ul style="list-style: none">';
tips = '<li>行政区划:' params.name '</li>';
tips = '<li>历史已报件:1000个</li>';
tips = '<li>最近上报时间:' new Date().toLocaleTimeString() '</li>';
tips = '</ul>';
return tips;
}
},
legend: {
show: true,
orient: 'vertical',
x: 'left',
data: ['玉溪 Top10', '大理 Top10', '保山 Top10'],
selectedMode: 'single',
selected: {
'保山 Top10': false,
'大理 Top10': false
},
textStyle: {
color: '#fff'
}
},
toolbox: {
show: true,
orient: 'vertical',
x: 'right',
y: 'center',
feature: {
mark: {show: true},
dataView: {show: true, readOnly: false},
restore: {show: true},
saveAsImage: {show: true}
}
},
dataRange: {
min: 0,
max: 100,
calculable: true,
color: ['#ff3333', 'orange', 'yellow', 'lime', 'aqua'],
textStyle: {
color: '#fff'
}
},
series: [
{
name: '云南',
type: 'map',
roam: true,
hoverable: false,
mapType: '云南',
itemStyle: {
normal: {
color: '#28363E',
borderColor: 'rgba(100,149,237,1)',
borderWidth: 1,
areaStyle: {
color: '#1b1b1b'
},
label: {
show: true,
textStyle: {
fontSize: 12,
color: 'white'
}
}
}
},
data: [],
markLine: {
smooth: true,
symbol: ['none', 'circle'],
symbolSize: 1,
itemStyle: {
normal: {
color: '#fff',
borderWidth: 1,
borderColor: 'rgba(30,144,255,0.5)'
}
},
data: [],
},
geoCoord: {
'普洱市': [100.7446, 23.4229],
'红河哈尼族彝族自治州': [103.0408, 23.6041],
'文山壮族苗族自治州': [104.8865, 23.5712],
'曲靖市': [103.9417, 25.7025],
'楚雄彝族自治州': [101.6016, 25.3619],
'大理白族自治州': [99.9536, 25.6805],
'临沧市': [99.613, 24.0546],
'迪庆藏族自治州': [99.4592, 27.9327],
'昭通市': [104.0955, 27.6031],
'昆明市': [102.9199, 25.4663],
'丽江市': [100.448, 26.955],
'西双版纳傣族自治州': [100.8984, 21.8628],
'保山市': [99.0637, 24.9884],
'玉溪市': [101.9312, 23.8898],
'怒江傈僳族自治州': [99.1516, 26.5594],
'德宏傣族景颇族自治州': [98.1299, 24.5874],
}
},
{
name: '昆明市',
type: 'map',
mapType: '云南',
data: [],
markLine: {
smooth: true,
effect: {
show: true,
scaleSize: 2,
period: 30,
color: '#fff',
shadowBlur: 10
},
itemStyle: {
normal: {
borderWidth: 1,
lineStyle: {
type: 'solid',
shadowBlur: 10
}
}
}
},
markPoint: {
symbol: 'emptyCircle',
symbolSize: function (v) {
return 10 v / 10
},
effect: {
show: true,
shadowBlur: 0
},
itemStyle: {
normal: {
label: {show: false}
},
emphasis: {
label: {position: 'top'}
}
}
}
}
]
};
function changeDataSource() {
var dataSourceId = parseInt($("#dataSourceId").val());
loadAll(dataSourceId, '数据交换监控');
}
/**
* 加载数据源,构造需要加入迁徙图的数据和连线信息
* @param dataSourceId 数据源 data.js中定义的对象
* @param title 标题
*/
function loadAll(dataSourceId, title) {
myChart.clear();
var data = h2.get(dataSourceId);
option.series[1].markLine.data = [];
//各市州到中心的连线数据
for (var i = 0; i < data.length; i ) {
var point = new Object();
point.name = data[i].name;
var centerPoint = new Object();
centerPoint.name = center;
var arr = new Array();
arr.push(centerPoint);
arr.push(point);
option.series[1].markLine.data.push(arr);
}
//流向数据
option.series[1].markPoint.data = data;
option.title.text = title;
myChart.setOption(option);
}
var h2 = new HashMap();
function initData() {
for (var i = 0; i < dataSource.length; i ) {
h2.put(dataSource[i].dataSourceId, dataSource[i].data);
}
}
window.onresize = function () {
myChart.resize();
}
option属性的配置是关键。
- 我们需要展示的是云南省的地图,其地图geojson的数据在source/chart/map.js作为一个amd模块已经定义好。
![](http://www.mk2048.com/web_upload/blog_imgs/7/https___user-gold-cdn-xitu-io_2018_6_21_164216fdbaf605f9_w-630_h-551_f-jpeg_s-58088.gif)
mapType指定为'云南',这个是在map模块里定义个一个省级地图数据:
![](http://www.mk2048.com/web_upload/blog_imgs/7/https___user-gold-cdn-xitu-io_2018_6_21_164216fdbb1eeede_w-581_h-131_f-jpeg_s-11241.gif)
geoCoord设置为每个市的中心坐标:
![](http://www.mk2048.com/web_upload/blog_imgs/7/https___user-gold-cdn-xitu-io_2018_6_21_164216fdc415f3c9_w-720_h-350_f-jpeg_s-23027.gif)
加载数据源
我们需要的数据有两部分:连线数据和起点数据:
/**
* 加载数据源,构造需要加入迁徙图的数据和连线信息
* @param dataSourceId 数据源 data.js中定义的对象
* @param title 标题
*/
function loadAll(dataSourceId, title) {
myChart.clear();
var data = h2.get(dataSourceId);
option.series[1].markLine.data = [];
//各市州到中心的连线数据
for (var i = 0; i < data.length; i ) {
var obj = new Object();
obj.name = data[i].name;
var obj1 = new Object();
obj1.name = center;
var arr = new Array();
arr.push(obj);
arr.push(obj1);
option.series[1].markLine.data.push(arr);
}
//流向数据
option.series[1].markPoint.data = data;
option.title.text = title;
myChart.setOption(option);
}
markLine的data属性为一个数组,其元素是{{name:'楚雄彝族自治州'},{name:'昆明市'}这种结构。
最后调用myChart.setOption(option);即可展示文章开头部分的效果了。
tips
如需切换其他省市地图,只需在option更改相应地图数据和坐标即可。
附项目地址:
end
思考:本文实现的是数据从多个城市上报到中心城市的效果。读者可自行做一个数据分发的效果,也就是数据从一个中心城市流出到多个城市。效果如下:
![](http://www.mk2048.com/web_upload/blog_imgs/7/https___user-gold-cdn-xitu-io_2018_6_21_164216fdc46f6557_w-600_h-442_f-gif_s-250553.gif)