Echarts3的离线地图组件,比echart2更容易实现省市区多级离线地图的展示。
当然echart2也是可以实现,由于echarts是基于canvas,加载一个地图无非就是加载一张图。而这张图,则是利用每张地图边界的经纬度,组成的一个面。理论上,只要给出一张地图边缘点的集合,用echarts,准确还说用canvas技术就能画出任何我们想要展示的地图形状。
实现思路:为了实现多级(省市区)地图的相互切换,本文采用单击鼠标事件触发页面进行下一级地图(如:从全国地图到湖南省的地图),采用双击鼠标事件返回上一级地图(如:从湖南省地图返回全国地图)。返回的上一级地图的实现方式也可以采用鼠标右键事件实现。鼠标右键可能比双击返回更好,因为双击容易跟单击冲突。
实现工具:echarts插件、地图json文件。
全国省市区的离线json文件,已上传到github:
主要要两种实现方法:区别主要在于如何返回上一级。
方法1:双击地图返回上一级地图;
方法2:右键点击“返回上一级”按钮进行返回。
以具体的代码,来介绍两种方法,先介绍它们公用的函数:loadMap。该函数主要用于加载地图。$.getJSON为jquery插件的ajax函数。
/**
加载地图:根据地图所在省市的行政编号,
获取对应的json地图数据,然后向echarts注册该区域的地图
最后加载地图信息
@params {String} mapCode:地图行政编号,for example['中国':'100000', '湖南': '430000']
@params {String} mapName: 地图名称
*/
function loadMap(mapCode, mapName) {
$.getJSON('china-main-city/' + mapCode + '.json', function (data) {
if (data) {
//向echarts插件注册地图
echarts.registerMap(mapName, data);
var option = {
tooltip: {
trigger: 'item',
formatter: '{b}'
},
series: [
{
name: '',
type: 'map',
mapType: mapName,
selectedMode : 'multiple',
label: {
normal: {
show: true
},
emphasis: {
show: true
}
},
data:[
]
}
]
};
myChart.setOption(option);
curMap = {
mapCode: mapCode,
mapName: mapName
};
} else {
alert('无法加载该地图');
}
});
}
方法1:采用用户单击下钻地图到下级地图;双击地图返回上级地图。由于双击受单击影响,故双击事件的响应方法延迟了250毫秒。这样就可以一旦检测到了双击事件,就立刻解除单击的回调事件。这样图表就只会响应双击事件。当用户单击时,如果可以下钻,则将当前地图信息存储到栈(利用栈先进后出的特性)便于获取返回的地图信息。如下代码所示:
/**
绑定用户切换地图区域事件
cityMap对象存储着地图区域名称和区域的信息(name-code)
当mapCode有值,说明可以切换到下级地图
同时保存上级地图的编号和名称
*/
myChart.on('mapselectchanged', function(params) {
clearTimeout(timeFn);
//由于单击事件和双击事件冲突,故单击的响应事件延迟250毫秒执行
timeFn = setTimeout(function(){
var name = params.batch[0].name;
var mapCode = cityMap[name];
if (!mapCode) {
alert('无此区域地图显示');
return;
}
loadMap(mapCode, name);
//将上一级地图信息压入mapStack
mapStack.push({
mapCode: curMap.mapCode,
mapName: curMap.mapName
});
}, 250);
});
/**
绑定双击事件,并加载上一级地图
*/
myChart.on('dblclick', function(params) {
//当双击事件发生时,清除单击事件,仅响应双击事件
clearTimeout(timeFn);
var map = mapStack.pop();
if (!mapStack.length && !map) {
alert('已经到达最上一级地图了');
return;
}
loadMap(map.mapCode, map.mapName);
});
方法2:采用图表的右键事件,再点击“返回上一级”按钮进行返回。方法一相比方法二的优点就是无需采用定时器进行延迟,即单击的回调事件可以立刻响应,无需延迟250毫秒。如下代码所示:
/**
绑定用户切换地图区域事件
cityMap对象存储着地图区域名称和区域的信息(name-code)
当mapCode有值说明可以切换到下级地图
此时保存上级地图的编号和名称
*/
myChart.on('mapselectchanged', function(params) {
var name = params.batch[0].name;
var mapCode = cityMap[name];
if (!mapCode) {
alert('无此区域地图显示');
return;
}
loadMap(mapCode, name);
//将上一级地图信息压入mapStack
mapStack.push({
mapCode: curMap.mapCode,
mapName: curMap.mapName
});
});
/**
绑定右键事件
*/
myChart.on('contextmenu', function(params) {
$('#contextMenu').css({
left: params.event.offsetX,
top: params.event.offsetY
}).show();
});
/**
响应图表的右键事件,返回上一级地图
*/
$('#contextMenu').on('click', function () {
$(this).hide();
//获取上一级地图信息
var map = mapStack.pop();
if (!mapStack.length && !map) {
alert('已经到达最上一级地图了');
return;
}
loadMap(map.mapCode, map.mapName);
});
单击下钻,双击返回整个代码如下:
<!DOCTYPE html>
<html>
<head >
<meta charset="utf-8">
<script type="text/javascript" src="echarts.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="china-main-city-map.js" charset="utf-8"></script>
</head>
<body>
<div id= "main" style="width:1350px;height:600px;"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
//存储切换的每一级地图信息
var mapStack = [];
var timeFn = null;
var curMap = {};
//初始化为中国地图
loadMap('100000', 'china');
/**
绑定用户切换地图区域事件
cityMap对象存储着地图区域名称和区域的信息(name-code)
当mapCode有值,说明可以切换到下级地图
同时保存上级地图的编号和名称
*/
myChart.on('mapselectchanged', function(params) {
clearTimeout(timeFn);
//由于单击事件和双击事件冲突,故单击的响应事件延迟250毫秒执行
timeFn = setTimeout(function(){
var name = params.batch[0].name;
var mapCode = cityMap[name];
if (!mapCode) {
alert('无此区域地图显示');
return;
}
loadMap(mapCode, name);
//将上一级地图信息压入mapStack
mapStack.push({
mapCode: curMap.mapCode,
mapName: curMap.mapName
});
}, 250);
});
/**
绑定双击事件,并加载上一级地图
*/
myChart.on('dblclick', function(params) {
//当双击事件发生时,清除单击事件,仅响应双击事件
clearTimeout(timeFn);
var map = mapStack.pop();
if (!mapStack.length && !map) {
alert('已经到达最上一级地图了');
return;
}
loadMap(map.mapCode, map.mapName);
});
/**
加载地图:根据地图所在省市的行政编号,
获取对应的json地图数据,然后向echarts注册该区域的地图
最后加载地图信息
@params {String} mapCode:地图行政编号,for example['中国':'100000', '湖南': '430000']
@params {String} mapName: 地图名称
*/
function loadMap(mapCode, mapName) {
$.getJSON('china-main-city/' + mapCode + '.json', function (data) {
if (data) {
echarts.registerMap(mapName, data);
var option = {
tooltip: {
trigger: 'item',
formatter: '{b}'
},
series: [
{
name: '',
type: 'map',
mapType: mapName,
selectedMode : 'multiple',
label: {
normal: {
show: true
},
emphasis: {
show: true
}
},
data:[
]
}
]
};
myChart.setOption(option);
curMap = {
mapCode: mapCode,
mapName: mapName
};
} else {
alert('无法加载该地图');
}
});
}
</script>
</body>
</html>
单击下钻,右键菜单返回,全部代码如下:
<!DOCTYPE html>
<html>
<head >
<meta charset="utf-8">
<script type="text/javascript" src="echarts.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="china-main-city-map.js" charset="utf-8"></script>
</head>
<body>
<div id= "main" style="width:1350px;height:600px;"></div>
<div id = "contextMenu" style = "position: absolute;background:#000;opacity:0.8;cursor: pointer;border-radius: 2px;padding:8px 30px;display:none;color: #fff;font-size:14px;">返回上一级</div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
//存储切换的每一级地图信息
var mapStack = [];
var curMap = {};
//初始化地图
loadMap('100000', 'china');
/**
绑定用户切换地图区域事件
cityMap对象存储着地图区域名称和区域的信息(name-code)
当mapCode有值说明可以切换到下级地图
此时保存上级地图的编号和名称
*/
myChart.on('mapselectchanged', function(params) {
var name = params.batch[0].name;
var mapCode = cityMap[name];
if (!mapCode) {
alert('无此区域地图显示');
return;
}
loadMap(mapCode, name);
//将上一级地图信息压入mapStack
mapStack.push({
mapCode: curMap.mapCode,
mapName: curMap.mapName
});
});
/**
绑定右键事件
*/
myChart.on('contextmenu', function(params) {
$('#contextMenu').css({
left: params.event.offsetX,
top: params.event.offsetY
}).show();
});
/**
响应图表的右键事件,返回上一级地图
*/
$('#contextMenu').on('click', function () {
$(this).hide();
//获取上一级地图信息
var map = mapStack.pop();
if (!mapStack.length && !map) {
alert('已经到达最上一级地图了');
return;
}
loadMap(map.mapCode, map.mapName);
});
/**
加载地图:根据地图所在省市的行政编号,
获取对应的json地图数据,然后向echarts注册该区域的地图
最后加载地图信息
@params {String} mapCode:地图行政编号,for example['中国':'100000', '湖南': '430000']
@params {String} mapName: 地图名称
*/
function loadMap(mapCode, mapName) {
$.getJSON('china-main-city/' + mapCode + '.json', function (data) {
if (data) {
echarts.registerMap(mapName, data);
var option = {
tooltip: {
trigger: 'item',
formatter: '{b}'
},
series: [
{
name: '',
type: 'map',
mapType: mapName,
selectedMode : 'multiple',
label: {
normal: {
show: true
},
emphasis: {
show: true
}
},
data:[
]
}
]
};
myChart.setOption(option);
//存储当前地图的信息
curMap = {
mapCode: mapCode,
mapName: mapName
};
} else {
alert('无法加载该地图');
}
});
}
</script>
</body>
</html>
总结:两种方法都有各自的优缺点,方法一相比二,操作更方便,但容易误操作;方法二,需要额外的右键操作,绑定dom进行回调处理。如果需要进一步对地图显示效果进行处理,可直接对loadMap函数的option对象进行操作,传入相应参数即可。其实,只要有展示地区的json轮廓数据,然后在china-main-city-map.js配置相应参数,这个设计和实现方法,完全可以实现多级(最多没有限制)地图的切换。
实际效果,如下图所示:
(1) 初始化为全国地图
(2)单击进入下级地图(如湖南地图)
(3)再单击进入下级地图(如湖南下面的长沙市地图)
(4)双击返回或者右键返回上一级地图
(5)双击返回或者右键返回上一级地图
下载地址:详细源码已经上传到了csdn,地址为:http://download.csdn.net/download/mulumeng981/9962651