ECHARTS实现区域、省份、市、区县的数据穿透
前言
目前Echarts官网有很多关于省市区3级穿透的案例,但是很少有区域、省、市、区4级穿透的案例,本案例采用SpringMVC结合JSP、Echarts、本地化地图JSON完成(本地json可替换成高德地区获取区划的API)
提示:以下是本篇文章正文内容,下面案例可供参考
一、Echarts是什么?
一个基于 JavaScript 的开源可视化图表库,
官网https://echarts.apache.org/
案例库网址:https://www.makeapie.com/explore.html
二、实现效果
1.初始化地图展示
2.钻取
区域–>省份
省份–>市
三、实现步骤
1.引入JS库
代码如下(示例):
<script type="text/javascript" src="/echarts/echarts.min.js"></script>
2.初始化HTML标签、存放Echarts图
代码如下(示例):
<div style="width: 100%;height:100%" id="Map"></div>
注意需要设置ID值,方便后续进行配置文件注册,需要设置宽高,不然会显示空白。
3.初始化配置文件
var mapOption = {
layoutCenter: ['60%', '65%'],//控制地图左边,上边的位置
layoutSize: "70%",//控制地图的大小
tooltip: { //格式化提示
trigger: "item",
formatter: function (p) {
let val = p.value;
if (!val) {
val = 0;
}
let txtCon = p.name + ":" + val.toFixed(2);
return txtCon;
}
},
title: {
show: true,
left: "center",
top: "15",
text: currentArea+currentTab,
textStyle: {//标题样式控制
color: "rgb(255,255,255)",
fontSize: 20
}
},
visualMap: {//刻度
min: 1,
max: 1,
left: "1%",
bottom:"3%",
showLabel: !0,
pieces:[],
textStyle: {
color: "#24CFF4"
},
show: !0
},
series: [{
name: "地图",
type: "map",//显示的类型
map: "china",//显示地图为中国地图
roam: true, //是否可缩放
zoom: 1, //缩放比例
data: [],//地图数据
label: {
normal: {
show: true,
color: "#000000", //省份标签字体颜色
fontSize: 16,
// fontWeight: 'bold',
areaStyle: {
color: '#ffffff',//默认的地图板块颜色
},
formatter: function (p) {//格式化显示各个省份名称,主要是为了不要显示的太长
switch (p.name) {
case "内蒙古自治区":
p.name = "内蒙古";
break;
case "西藏自治区":
p.name = "西藏";
break;
case "新疆维吾尔自治区":
p.name = "新疆";
break;
case "宁夏回族自治区":
p.name = "宁夏";
break;
case "广西壮族自治区":
p.name = "广西";
break;
case "香港特别行政区":
p.name = "香港";
break;
case "澳门特别行政区":
p.name = "澳门";
break;
default:
break;
}
return p.name;
}
},
emphasis: {
show: true,
color: "#000000"
}
},
itemStyle: {//地图边界线样式
normal: {
// areaColor: "#24CFF4",
borderColor: "#fea8a6",
// borderWidth: 1.3,
shadowBlur: 1,
shadowColor: "#fffdfe",
// shadowOffsetX: 7,
// shadowOffsetY: 6
},
emphasis: {
areaColor: "#8dd7fc",
borderWidth: 1.6,
shadowBlur: 25
}
}
}]
};
配置文件可参考官网,里面的数据需要通过JS动态加载
3.获取地图数据
//热力图
//初始化方法,100000为全国地图编码
getMapJson(100000);
/**
* adcodes: 区域编码数组:各区域存放的省份编码,如华南区域
* isArea: 是否不钻取数据,true:不钻取 false:钻取
**/
function getMapJson(adcodes,cityCode,isArea) {
var that = this;
city_code = cityCode.toString();
let mapData = [];
//不钻取数据,只匹配数据
if (isArea) {
//获取本地地图JSON
$.get('/echarts/json/china.json',function(ret) {
//全国省份数据
var areaJson = [];
mapData = ret.features;
for (let i = 0; i < adcodes.length; i++) {
for (let j = 0; j < mapData.length; j++) {
//不允许用全等于,后端id为字符串
if (adcodes[i] == mapData[j].properties.adcode) {
areaJson.push(mapData[j]);
}
}
}
that.geoJson.features = areaJson;
area_pri_city_type = "PROVINCE";
//获取子集展示数据
that.getMapData();
});
//钻取数据
} else {
var type = "";
if(adcodes.length === 1){
let code = adcodes.toString();
$.get('/echarts/json/province/'+code+'.json',function(res) {
mapData = res.features;
//只钻取数据到市级,如果是直辖市,则不往下钻取,需要钻取区县的可以把这个去掉
if (adcodes[0] != "110000" && adcodes[0] != "120000" && adcodes[0] != "310000" && adcodes[0] != "500000" && mapData.length > 0 && mapData[0].properties.level === "district") {
return;
}
//无地图数据
if (mapData.length === 0) {
return;
}
switch (mapData[0].properties.level) {
case "province":
area_pri_city_type = "AREA";
type = "AREA";
break;
// case "city":
default:
area_pri_city_type = "CITY";
type = "CITY";
break;
// default:
// type = "COUNTY"
}
//判断是否有子集数据
if (mapData.length > 0) {
that.geoJson.features = mapData;
} else if (mapData.length === 0) {
that.geoJson.features = [];
if (that.geoJson.features.length === 0) return;
}
//获取子集展示数据
that.getMapData();
});
}
}
}
//关于地图省份合并参考这位大佬的文章,更改而来
//文章地址:https://blog.csdn.net/weixin_33743661/article/details/93469931?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-8.baidujs&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-8.baidujs
//获取数据
function getMapData() {
//省市区使用getMapData获取数据
//地图、柱状图数据
if (this.parentInfo.length === 1 && is_init) {
//后台封装的区域及下级省份的名称,编码数据
//数据格式:
//var params = {
// names: [//把各个大区的省份用二维数组分开
// ['北京','天津','河北','山西','内蒙古'],
// ["黑龙江","吉林","辽宁"],
// ['山东','江苏','安徽','江西','浙江','福建','上海','台湾'],
// ['河南','湖北','湖南'],
// ['广东','广西','海南','香港','澳门'],
// ['重庆','四川','云南','西藏','贵州'],
// ['陕西','甘肃','青海','宁夏','新疆']
// ],
// properties: {//自定义大区的名字,要和上面的大区省份一一对应
// name: ['华北','东北','华东','华中','华南','西南','西北'],
// cp: [//经纬度可以自己随意定义
// [116.24,39.54],
// [126.32,43.50],
// [121.28,31.13],
// [114.20,30.32],
// [113.15,23.08],
// [104.04,30.39],
// [103.49,36.03]
// ]
// }
// };
var mapPriAreaDataList = '${mapPriAreaDataList}';
// var jsonData = $.parseJSON(mapPriAreaDataList);
data = eval(mapPriAreaDataList);
var params = {
names:[],//省份名称
adcode:[],//大区编码
properties:{
name:[],//大区名称
cp:[],//经纬度,中文显示的位置
cityCode:[]//省份获取市区编码
}
};
data.forEach(function(item,index){
params.names[index] = item.childName;
params.adcode[index] = item.value;
params.properties.name[index] = item.name;
params.properties.cp[index] = item.description;
params.properties.cityCode[index] = item.childValue;
});
//合并省份图层
mergeProvinces(this.geoJson, params.names, params.properties, params.adcode);
is_init = false;
}
//获取时间
let dateTime = $("#fillDateTime").val();
//获取组织
let orgId = $("#jqCodeId").val();
//查询后台地图数据
$.getJSON("示例路径?code="+city_code+"&type="+area_pri_city_type+"&dateTime="+dateTime+"&orgId="+orgId, function (res) {
// console.log(res,1);
haltMapData = res;
//循环地图数据
//格式化数据,显示新签合同额
var echartsData = formatData(res,indicatorType);
//注册初始化地图
initEcharts(echartsData.mapData,echartsData.projectBarData,echartsData.areaBarData);
//更新8大指标数据
});
}
4.合并省份图层
//合并大区,主要是根据格式化的地图省份编码,合并边界线
function mergeProvinces(chinaJson, names, properties,adcodes) {
//合并大区里省份的coordinates
var features = chinaJson.features;
var polygons = [];
var polygons2 = [];
for (var i = 0; i < names.length; i++) {
var polygonsCoordinates = [];
var polygonsEncodeOffsets = [];
for (var z = 0; z < names[i].length; z++) {
for (var j = 0; j < features.length; j++) {
if (features[j].properties.name === names[i][z]) {
if (features[j].geometry.coordinates[0].constructor === String) {
//合并coordinates
for (var l = 0; l < features[j].geometry.coordinates.length; l++) {
polygonsCoordinates.push(features[j].geometry.coordinates[l]);
}
} else if (
features[j].geometry.coordinates[0].constructor === Array
) {
for (var k = 0; k < features[j].geometry.coordinates.length; k++) {
for (var d = 0; d < features[j].geometry.coordinates[k].length; d++) {
polygonsCoordinates.push(
features[j].geometry.coordinates[k][d]
);
}
}
}
console.log(features[j].geometry.encodeOffsets,features[j]);
if(features[j].geometry.encodeOffsets[0].constructor == String){//合并encodeOffsets
polygonsEncodeOffsets.push(features[j].geometry.encodeOffsets);
}else if(features[j].geometry.encodeOffsets[0].constructor == Array){
for(var k=0;k<features[j].geometry.encodeOffsets.length;k++){
if(features[j].geometry.encodeOffsets[k][0].constructor == Array){
for(var e=0;e<features[j].geometry.encodeOffsets[k].length;e++){
polygonsEncodeOffsets.push(features[j].geometry.encodeOffsets[k][e]);
}
}else{
polygonsEncodeOffsets.push(features[j].geometry.encodeOffsets[k]);
}
}
}
break;
}
}
}
polygons.push(polygonsCoordinates);
polygons2.push(polygonsEncodeOffsets);
}
// 构建新的合并区域
var features = [];
for (var a = 0; a < names.length; a++) {
var feature = {
id: features.length.toString(),
type: "FeatureCollection",
geometry: {
type: "Polygon",
coordinates: polygons[a],
encodeOffsets: polygons2[a]
},
properties: {
name: properties.name[a] || "",
childNum: polygons[a].length,
adcode:adcodes[a] || ""
}
};
if (properties.cp[a]) {
feature.properties.cp = properties.cp[a];
}
// 将新的合并区域添加到地图中
features.push(feature);
}
this.geoJson.features = features;
}
5.注册地图
function initEcharts(mapData,projectBarData,areaBarData) {
//获取标签
this.myChart = echarts.init(document.getElementById("Map"));
//这里是切换地图,china标识全国地图,map标签区域地图(区域、省、市级、区县)
if (this.parentInfo.length === 1) {
echarts.registerMap('china', this.geoJson); //注册
mapOption.series[0].map = "china";
} else {
echarts.registerMap('Map', this.geoJson); //注册
mapOption.series[0].map = "Map";
}
//这里是获取后台地图展示的数据,如果只是看地图,这块可注释
var min = mapData.length > 0 ?mapData[mapData.length-1].value:0;;
var max = mapData.length > 0 ?mapData[0].value:0;
//设置地图刻度颜色方法
setAreaColor(max,min);
//判断目前展示的是区域还是全国地图,调整地图中心点和大小
if(area_pri_city_type !== "AREA"){
mapOption.layoutCenter = ["50%","50%"];
mapOption.layoutSize = "100%";
}else{
mapOption.layoutCenter = ["60%","65%"];
mapOption.layoutSize = "70%";
}
//设置地图数据和标题
mapOption.visualMap.min = min;
mapOption.visualMap.max = Math.ceil(max / 5) * 5;
mapOption.visualMap.pieces = piecesArray;
mapOption.series[0].data = mapData;
mapOption.title.text = currentArea+currentTab;
// mapOption.toolbox.feature.saveAsImage.name = currentArea+currentTab;
//注册地图
this.myChart.setOption(mapOption,true);
// //点击前解绑,防止点击事件触发多次
this.myChart.off('click');
//地图点击实现,点击传入编码和名称,进行钻取
this.myChart.on('click', this.echartsMapClick);
}
6.实现地图点击向下钻取
//点击下钻
function echartsMapClick(params) {
if (!params.data) {
return
}
//省份CODE数组
let isArea = true;
let data = Object.assign({},params.data);
//后台获取各个区域对应的省份编码数组
var mapPriAreaDataList = '${mapPriAreaDataList}';
priAreaData = eval(mapPriAreaDataList);
let areaData = priAreaData.filter(function(item ) {
return item.name === data.name;
});
//点击的的区域是名称能匹配上,则编码为这个区域的省份编码,进行匹配显示,否则直接钻取,省-->市-->区县
if(areaData[0] != null){
data.cityCode = areaData[0].childValue;
}else{
isArea = false;
}
parentInfo.push({
cityName: data.name,
code: data.cityCode ? data.cityCode : 0
});
//增加导航路径,可进行切换
setBreadcrumb(isArea,data.cityCode,params);
//获取子集地域,点击继续获取数据,刷新地图
getGeoJson(isArea ? data.cityCode : [data.cityCode],params.data.cityCode, isArea);
}