效果展示
需求
最近遇到一个展示某个地区以及其下级地区并且在地区上标注点的需求。要求是:
- 默认展示全部地区地图,点击地区中的下级地区,切换成下级地区的地图。
- 地图能够缩放,地图中需要标记点位。
- 地图需要与外部联动,分为三个层级:全部地区、下级地区、具体点位,点击这三个层级在外部的响应事件不一样。
技术选型
由于需求中并不需要展示比较精细的地图内容,所以针对该需求,采用echarts地图来实现而未采用百度地图、高德地图等。
结构目录
- components文件夹用来管理子组件
- map文件夹用来管理地图JSON
- set.js是地图配置文件
构建地图步骤
- 注册地图
echart使用定制地图,需要进行注册,使用echarts.registerMap来进行注册,有三种注册的方式,方法详情如下:
js
( mapName: string,
opt:{
geoJSON: Object | string; specialAreas?: Object;
}
) |
( mapName: string,
opt:{
svg: Object | string;
}
) |
( mapName: string, geoJSON: Object | string, specialAreas?: Object )
注册可用的地图,只在 geo 组件或者 map 图表类型中使用。 使用方法见 option.geo。
参数:
-
opt
geoJSON
可选。GeoJson 格式的数据,具体格式见 geojson.org/。可以是 JSON 字符串,也可以是解析得到的对象。这个参数也可以写为geoJson
,效果相同。svg
可选。从v5.1.0
开始支持SVG 格式的数据。可以是字符串,也可以是解析得到的 SVG DOM 对象。更多信息参见 SVG 底图。specialAreas
可选。将地图中的部分区域缩放到合适的位置,可以使得整个地图的显示更加好看。只在geoJSON
中生效,svg
中不生效。
在这里我们使用echarts.registerMap(mapName: string, geoJSON: Object)
来进行注册地图。
1.1. 获取定制地图的JSON
这里我们借助阿里云数据可视化平台-DATAV来进行JSON的获取。
整体界面的右侧是使用方式,根据使用步骤进行操作,本次实例最后使用其他类型,直接将其下载下来。
JSON文件下载下来之后,整理到map文件夹中。
- 初始化echarts容器
html
<div class="settlement-content-item-top">
<!-- <echarts-map /> -->
<div class="map">
<div ref="content" class="map-content"></div>
<div class="back" @click="goBack">全部区域</div>
<div class="map-title">{{ chartName }}</div>
</div>
</div>
js
init() {
......
// 初始化容器
this.myChart = echarts.init(this.$refs.content);
// loading
this.myChart.showLoading();
// 设置地图
this.setMap();
this.option && this.myChart.setOption(this.option);
window.addEventListener("resize", this.myChart.resize);
// 注册事件,便于后续发送地图信息给别的组件
this.myChart.on("click", ({ name, data }) => {
// 点击了点
if (data) {
......
} else {
// 点击了区域
......
}
});
},
- 设置地图方法
- 点击地图会调用该方法,根据层级来判断加载哪个JSON地图数据,以展示不同的地图
- 然后设置地图的数据以加载图中的点。
js
// chartName不传就使用默认值
setMap(chartName = "xxx", medicalInstitutionCode = "") {
// 注册地图,第一个参数是名称,第二个参数是对应的地图JSON值
echarts.registerMap(chartName, this.chartMap.get(chartName).json);
// 隐藏loading效果
this.myChart.hideLoading();
// 设置echarts options
this.myChart.setOption(
// 赋值操作也是有返回值的,这里赋值完成之后,把结果给了this.myChart.setOption方法
// setOption方法来自于set.js文件
(this.option = setOption(
chartName,
this.hospitalOptionMap.get(medicalInstitutionCode),
this.chartMap.get(chartName).center
))
);
}
- 设置option方法「核心」
js
// 参数:地图名、数据、地图中心经纬度
export const setOption = (map, data, center) => {
return {
tooltip: {
trigger: "item",
formatter: "{b}"
},
visualMap: {
show: false, //显示数据区间查看器
inRange: {
color: ["#48b2fd"]
}
},
// 写入经纬度标注点所需
geo: {
map,
center,
roam: true,
zoom: 1,
label: {
normal: {
// 显示省份标签
show: false,
textStyle: {
color: "#fff",
fontSize: 10
}
}
},
itemStyle: {
color: "#ddb926",
normal: {
// 地图区域颜色
areaColor: "#1a456b",
// 地图描边颜色
borderColor: "#1BB0D4",
// 地图描边大小
borderWidth: 1
},
// 高亮时的样式
emphasis: {
areaColor: "#1BB0D4",
borderColor: "#1BB0D4",
borderWidth: 1
}
}
},
// 两种方式:
// 1、geo
// 2、series的type=map,这个不能在地图上标点,只能是tooltip
series: [
// {
// name: map,
// type: "map",
// map,
// zoom: 1.2,
// label: {
// show: true,
// color: "#fff"
// },
// itemStyle: {
// normal: {
// borderColor: "#2ab8ff",
// borderWidth: 1.5,
// areaColor: "#12235c"
// },
// emphasis: {
// areaColor: "#2AB8FF",
// borderWidth: 0,
// color: "green"
// }
// },
// selectedMode: false
// },
{
type: "effectScatter",
coordinateSystem: "geo",
showEffectOn: "render",
// 涟漪特效相关配置
rippleEffect: {
// 动画的周期(秒数)
period: 15,
// 动画中波纹的最大缩放比例
scale: 2,
// 波纹的绘制方式
brushType: "fill"
},
hoverAnimation: true,
itemStyle: {
shadowBlur: 10,
shadowColor: "#333"
// normal: {
// color: "#000"
// }
},
data,
selectedMode: false
// 模拟数据
// data: [
// { name: "医院2", value: [86.165967, 41.749112, 10] },
// { name: "医院3", value: [84.261084, 41.783598, 50] },
// { name: "医院4", value: [86.263739, 41.350774, 100] },
// { name: "医院5", value: [88.175899, 39.029217, 150] },
// { name: "医院7", value: [86.571444, 42.066777, 400] },
// { name: "医院8", value: [86.3904, 42.330431, 500] },
// { name: "医院9", value: [86.883112, 42.287424, 600] },
// { name: "医院10", value: [86.883112, 42.287424, 70] },
// ],
}
]
};
};
- 传递地图控件数据,联动外部组件
js
// 发送数据出去
sendData(chartName = "巴音郭勒蒙古自治州", medicalInstitutionCode) {
// 防抖
clearTimeout(this.timeId);
this.timeId = setTimeout(() => {
let [
{ regionCode, regionName, medicalInstitutionName } = {
regionCode: this.chartMap.get(chartName).regionCode,
regionName: chartName,
medicalInstitutionName: ""
}
] = this.hospitalOptionMap.get(this.formData.hospital);
if (this.chartLevel === "all") {
regionCode = "";
regionName = "";
medicalInstitutionName = "";
}
// 自定义发送数据
this.reqParams = {
// 地区编码
regionCode,
// 地区名称
regionName,
// 医院编码
medicalInstitutionCode,
// 医院名称
medicalInstitutionName,
// 开始时间
startDate: this.formData.time[0],
// 结束时间
endDate: this.formData.time[1],
// 整个州、整个县/市、整个医院
type: this.getType(regionCode, medicalInstitutionCode)
};
}, 500);
},
页面联动逻辑
地图控件单独做一个单元,带动其他控件;地图控件变化会传递参数,其他组件监听到参数改变,随之改变。
总结
本文记录使用echarts地图geo功能的应用实例,遇到相同需求的朋友可以参考。