章
目
录
使用ECharts绘制中国地图是常见需求,今天就给大家分享一种利用CDN和阿里地图资源来实现的方法,而且无需下载JSON文件,方便又高效。
一、基础设置:防止403错误
在项目的index.html
文件里,添加下面这行代码,它的作用是防止出现403错误:
<meta name="referrer" content="no-referrer" />
这行代码设置了页面的引用策略,避免在请求资源时因引用问题导致403错误,为后续顺利加载地图资源做好准备。
二、数据与图表初始化
接下来,要对数据赋值,同时初始化图表和配置项option
。这里以初始化全国地图配置为例:
// 初始化绘制全国地图配置
option: {
backgroundColor: "transparent", // 设置背景色透明
// 必须设置
tooltip: {
show: false
},
// 地图阴影配置
}
在这段代码中,设置了地图的背景为透明,并且暂时隐藏了提示框tooltip
。大家可以根据实际需求,对这些初始配置进行调整。
三、挂载阶段:初始化地图相关操作
在mounted
钩子函数中,主要进行地图初始化、获取地图以及获取图表的操作:
mounted() {
this.initMap();
this.getMap();
this.myChart = window.echarts.init(document.getElementById("centerMap"));
}
initMap()
和getMap()
是自定义的方法,分别用于初始化地图数据和获取地图资源。window.echarts.init(document.getElementById("centerMap"))
则是使用ECharts的init
方法,通过传入对应的DOM元素ID,来初始化一个ECharts图表实例。
四、初始化地图:获取数据并绘制
initMap
函数主要负责从阿里地图获取数据,注册地图,绘制地图并绑定点击事件:
async initMap() {
document.getElementById("back").style.display = "none";
await axios
.get(`https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`)
.then((res) => {
// 获取所有省份
let shengAll = this.getChildMap(res.data);
// 注册大地图
window.echarts.registerMap("china", res.data);
// 绘制地图
this.renderMap("china", shengAll);
// 绑定点击地图区域事件
this.myChart.on("click", this.clickMap);
});
}
这里通过axios.get
从阿里云的地图数据接口获取中国地图的JSON数据。拿到数据后,先调用getChildMap
方法处理数据,获取所有省份信息。接着使用window.echarts.registerMap
注册地图,renderMap
方法绘制地图,最后绑定点击事件clickMap
,方便后续实现点击地图的交互功能。
五、点击地图:切换地图层级
点击地图后,要根据点击的区域判断地图类型,并显示相应层级的地图:
clickMap(params) {
document.getElementById("back").style.display = "block";
const name = params.name;
const adcode = this.getAdcodeFromGeoJSON(name);
const geoLevel = this.getAdcodeFromGeoLevel(name);
if (geoLevel == "province" || geoLevel == "city") {
if (name == "台湾省") {
this.$message.warning("已经是最后一层地图了");
} else {
axios
.get(`https://geo.datav.aliyun.com/areas_v3/bound/${adcode}_full.json`)
.then((res) => {
// 注册省级地图
window.echarts.registerMap(params.name, res.data);
// 获取当前省下所有市
let shiAll = this.getChildMap(res.data);
this.renderMap(params.name, shiAll);
});
}
} else {
this.$message.warning("没有更小的地图了");
// this.renderMap("china");
}
}
这段代码中,先获取点击区域的名称name
,再通过getAdcodeFromGeoJSON
和getAdcodeFromGeoLevel
方法获取对应的行政区划代码adcode
和地图层级geoLevel
。如果点击的是省份或城市,且不是台湾省,就获取该区域的详细地图数据,注册地图并绘制;如果点击的区域没有更小层级的地图,则给出提示。
六、辅助方法:获取信息
(一)获取adcode和地图类型
getAdcodeFromGeoJSON
方法用于从GeoJSON数据中获取adcode
:
getAdcodeFromGeoJSON(name) {
const geoJSON = window.echarts.getMap(this.option.geo.map).geoJSON;
for (let feature of geoJSON.features) {
if (feature.properties.name === name) {
return feature.properties.adcode;
}
}
return null;
}
这个方法通过遍历当前地图的GeoJSON数据,找到与点击名称匹配的区域,返回其adcode
,找不到则返回null
。
getAdcodeFromGeoLevel
方法用于获取地图类型:
getAdcodeFromGeoLevel(name) {
const geoLevel = window.echarts.getMap(this.option.geo.map).geoJSON;
for (let feature of geoLevel.features) {
if (feature.properties.name === name) {
return feature.properties.level;
}
}
return null;
}
该方法与上面类似,只不过返回的是匹配区域的地图层级信息。
(二)获取下级所有地名
getChildMap
方法用于获取下级所有地名:
getChildMap(data) {
let childMapAll = [];
// value为鼠标悬停地名显示的数据
for (var i = 0; i < data.features.length; i++) {
childMapAll.push({
name: data.features[i].properties.name,
value: 0
});
}
return childMapAll;
}
这个方法遍历传入的地图数据,将每个区域的名称和初始值0
组成对象,添加到数组中,最后返回包含所有下级地名的数组。
七、渲染地图:配置与更新
renderMap
方法用于修改ECharts配置并重新渲染地图,实现地图的缩放、拖动等功能:
renderMap(map, data) {
// 标题
this.option.geo = {
map: map,
// 这里必须定义,不然后面series里面不生效
tooltip: {
show: false
},
label: {
show: false
},
zoom: 1.03,
silent: true, // 不响应鼠标时间
show: true,
roam: false, // 地图缩放和平移
aspectScale: 0.75,
layoutSize: "108%",
itemStyle: {
normal: {
borderColor: "rgba(147, 235, 248, 1)",
borderWidth: 0.5,
color: {
type: "linear-gradient",
x: 0,
y: 1500,
x2: 2500,
y2: 0,
colorStops: [
{
offset: 0,
color: "#009DA1" // 0% 处的颜色
},
{
offset: 1,
color: "#005B9E" // 50% 处的颜色
}
],
global: true // 缺省为 false
},
opacity: 0.5
},
emphasis: {
areaColor: "#2a333d"
}
},
// 地图区域的多边形 图形样式 阴影效果
// z值小的图形会被z值大的图形覆盖
top: "18%",
left: "center",
// 去除南海诸岛阴影 series map里面没有此属性
regions: [
{
name: "南海诸岛",
selected: false,
emphasis: {
disabled: true
},
itemStyle: {
areaColor: "#00000000",
borderColor: "#00000000"
}
}
],
z: 1
};
this.option.series = [
// 地图配置
{
type: "map",
map: map,
zoom: 1,
tooltip: {
show: false
},
label: {
show: true, // 显示省份名称
color: "#04CFF5",
align: "center"
},
top: "18%",
left: "center",
aspectScale: 0.75,
layoutSize: "108%",
roam: false, // 地图缩放和平移
itemStyle: {
borderColor: "#0FA3F0", // 省分界线颜色 阴影效果的
borderWidth: 1,
areaColor: "#065CAE",
opacity: 1
},
// 去除选中状态
select: {
disabled: true
},
emphasis: {
// 聚焦后颜色
disabled: false, // 开启高亮
label: {
align: "center",
color: "#04CFF5"
},
itemStyle: {
color: "#ffffff",
areaColor: "#0a8bd8" // 阴影效果 鼠标移动上去的颜色
}
},
z: 2
},
// 点
{
name: "companyPoint",
type: "effectScatter",
coordinateSystem: "geo",
showEffectOn: "render",
// zlevel: 2, // zlevel用于 Canvas 分层 相同的绘制在同一个canvas上
rippleEffect: {
number: 3, // 波纹数量
period: 4, // 动画周期 数值越大,波动越慢
scale: 3.5, // 动画中波纹的最大缩放比例
brushType: "stroke" // 波纹的绘制方式 stroke fill
},
label: {
show: false,
position: "right",
formatter: "{b}",
color: "#97e9e1",
fontSize: 14
},
symbol: "circle",
symbolSize: 10,
tooltip: {
show: true,
padding: 0,
borderWidth: 0,
backgroundColor: "rgba(17, 132, 87,0.8)",
textStyle: {
fontSize: 14,
color: "#fff"
},
formatter: function (params) {
// console.log(params, 222);
var data = params.data;
return (
" " +
"所属用户:" +
data.name +
"<br>" +
" " +
"设备编号:" +
data.deviceId +
"<br>" +
" " +
"位置描述:" +
data.location +
" " +
"<br>" +
" " +
"数据时间:" +
data.dataTime
);
}
},
z: 4
}
];
// 重新渲染echarts
if (map == "china") {
this.option.geo.layoutCenter = ["50%", "65%"];
this.option.series[0].layoutCenter = ["50%", "65%"];
this.option.geo.roam = false;
this.option.series[0].roam = false; // 地图缩放和平移
} else {
this.option.geo.layoutCenter = ["50%", "50%"];
this.option.series[0].layoutCenter = ["50%", "50%"];
this.option.geo.roam = true;
this.option.series[0].roam = true; // 地图缩放和平移
this.myChart.on("georoam", (params) => {
var option = this.myChart.getOption(); //获得option对象
if (params.zoom != null && params.zoom != undefined) {
//捕捉到缩放时
option.geo[0].zoom = option.series[0].zoom; //下层geo的缩放等级跟着上层的geo一起改变
option.geo[0].center = option.series[0].center; //下层的geo的中心位置随着上层geo一起改变
this.myChart.getZr().on("mousewheel", (event) => {
var zoom = option.geo[0].zoom;
var zooms = option.series[0].zoom;
var newZoom = event.wheelDelta > 0? zoom * 2 : zoom / 2;
var newZooms = event.wheelDelta > 0? zooms * 2 : zooms / 2;
newZoom = Math.max(1, Math.min(200, newZoom)); // 限制缩放级别
newZooms = Math.max(1, Math.min(200, newZooms)); // 限制缩放级别
this.myChart.setOption(
{
geo: {
zoom: newZoom
},
series: [
{
zoom: newZooms
}
]
},
{ lazyUpdate: true }// 是否延迟更新
);
});
} else {
//捕捉到拖曳时
option.geo[0].center = option.series[0].center; //下层的geo的中心位置随着上层geo一起改变
this.myChart.setOption(option, { lazyUpdate: true }); //设置option// 是否延迟更新
}
});
}
this.option.series[1].data = this.provinceData; // 假设数据加载到data变量中
// // 更新图表数据
this.myChart.setOption(this.option, true); // 第二个参数为true表示不合并之前的option,而是完全替换
//随着屏幕大小调节图表
window.addEventListener("resize", () => {
this.myChart.resize();
});
}
这个方法配置了地图的各种属性,包括地图样式、缩放、拖动、标记点等。根据传入的地图名称,设置不同的布局和交互方式。最后更新图表数据,并添加监听窗口大小变化的事件,使图表能自适应屏幕变化。
通过以上步骤,我们就利用CDN和阿里地图资源,完成了ECharts中国地图的开发,并且实现了地图层级切换、缩放、拖动等功能。大家可以根据实际项目需求,对代码进行进一步优化和扩展。希望这篇文章能帮助到正在做相关开发的朋友们。