Vue内使用echarts(4.9.0版本)插件,绘制气泡地图,含默认高亮区域和地图自定义点击事件。效果和全部代码如下:
展示效果
1. 静态图
2. 动态图
代码部分
1. template部分
<template>
<div class="china-map">
<p class="title">{{nowProvince}}</p>
<!-- 左上角固定框部分 -->
<div class="left">
<ul class="left_ul">
<li
class="left_li"
v-for="(item, index) of provinceInfo"
:key="index"
:style="{'--color': item.color}"
>
<span>{{item.value}}</span>
<label>{{item.name}}</label>
</li>
</ul>
</div>
<!-- 地图 -->
<div id="chinaMapEle"></div>
</div>
</template>
2. Js部分
<script>
import "echarts/map/js/china.js";//注册地图铺底的中国省份数据,注意:仅echarts 4.x版本才有map文件夹,5.x版本取消map文件了
import echarts from "echarts";
export default {
name: "ChinaMap",
data() {
return {
nowProvince: "上海",//记录当前选中(高亮)区域的省份名称
chart: null, //图表的dom
chinaData: [],//全国34个省份的基础数据
scatterData: [],//气泡的基础数据
provinceInfo: [//左上角固定框部分内容
{name: "公司总数", value: 0, color: "#94BCFF"},
{name: "小微企业数", value: 0, color: "#94BCFF"},
{name: "中型企业数", value: 0, color: "#41D2BD"},
{name: "大型企业数", value: 0, color: "#FFD394"},
]
}
},
created() {
this.chinaData = echarts.getMap("china").geoJson.features;//获取全国34个省份的基础数据
this.scatterData = this.setScatterData();//设置气泡数据
this.getProniceData('310000');//上海Id:310000
},
mounted() {
this.chart = echarts.init(document.getElementById("chinaMapEle"));
this.drawMap();
},
methods: {
drawMap() {
let options = {//每个属性含义可参考echarts官网的配置手册进行了解
geo: {
map: "china",
center: "",
zoom: 1.1,
itemStyle: {//地图各省份区域属性
areaColor: "rgba(129, 156, 230, 0.3)",
borderColor: "rgba(142, 171, 255, 0.2)",
borderWidth: 2
},
emphasis: {//区域高亮时属性
label: {
show: false,
},
itemStyle: {
areaColor: "rgba(129, 156, 230, 0.3)",
borderColor: "#94BCFF",
borderWidth: 3,
shadowColor: "#94BCFF",
shadowBlur: 5
}
}
},
series: [
{//地图层:属性见上述geo
type: "map",
map: "china",
geoIndex: 0
},
{//气泡层
name: "气泡",
type: "scatter",
coordinateSystem: "geo",
symbolSize: 10,//统一设置气泡大小为10。也可以在data内根据value[3]数值来设置气泡的不同大小
label: {//气泡和文字标签
show: true,
color: "#FFFFFF",
formatter: "{b}",//就是省份名-name
position: "top",
distance: 3,//省份名与气泡之间的距离
},
itemStyle: {//气泡属性
color: "#94BCFF",
borderColor: "rgba(148, 188, 255, 0.2)",
borderWidth: 5
},
emphasis: {//高亮时属性
label: {
show: true,
fontSize: 18,
fontWeight: "bold",
},
itemStyle: {
color: "#FFFFFF",
borderColor: "#94BCFF",
borderWidth: 3,
shadowColor: "#94BCFF",
shadowBlur: 10
}
},
data: this.scatterData,
}
],
};
this.chart.setOption(options);
this.setAreaHighlight(this.nowProvince);//设置默认高亮区域
//监听地图点击事件
this.chart.off("click");
this.chart.on("click", params => this.handleMapClick(params));
},
/**
* 初始化气泡数据集合
* return 返回的数据结构:
* [
* { id: "省份Id", name: "省份名称", value: [经度, 纬度, 固定数值1]},
* { id: "省份Id", name: "省份名称", value: [经度, 纬度, 固定数值1]},
* ]
* 固定数值1: 通常被用来作为设置气泡大小的依据。
*/
setScatterData() {
let scatterData = [];
this.chinaData.forEach(province => {
scatterData.push({
id: province.id,//省份id,一般用于请求数据的唯一参数标识
name: province.properties.name,
value: [...province.properties.cp, 1]
})
})
return scatterData;
},
/**
* 设置区域高亮
* @param name series中的name值,也是区域(省份)名称
*/
setAreaHighlight(name) {
this.chart.dispatchAction({
type: "highlight",
seriesIndex: 0,//地图层
name: name
});
this.chart.dispatchAction({
type: "highlight",
seriesIndex: 1,//气泡层
name: name
});
},
/**
* 取消区域高亮
* @param name series中的name值,也是区域(省份)名称
*/
setAreaDownplay(name) {
this.chart.dispatchAction({
type: "downplay",
seriesIndex: 0,//地图层
name: name
});
this.chart.dispatchAction({
type: "downplay",
seriesIndex: 1,//气泡层
name: name
});
},
/**
* 区域点击后的动作
* @param data 击中的seriesIndex之dataIndex的对象信息{}
*/
handleMapClick(data) {
let { name, dataIndex } = data;
//判断击中区域是否为当前高亮区域,若是则不做任何动作;若不是则替换高亮区域
if(name !== this.nowProvince) {
this.setAreaDownplay(this.nowProvince);//1.将原来的高亮区域取消
this.nowProvince = name; //2. 记录最新的高亮区域(省份)名称
this.setAreaHighlight(this.nowProvince);//3.将新的区域置为高亮
if(this.scatterData[dataIndex]) {//铺底数据内含有此省份id信息
this.getProniceData(this.scatterData[dataIndex].id);//4.(可选)自定义请求数据
}else {//铺底数据内不含有此省份id信息
this.getProniceData('-1');//4.(可选)自定义请求数据
}
}
},
/**
* 获取省份的数据
* @param proId 省份Id
*/
getProniceData(pronId) {
// console.log("这里可自定义一些数据处理逻辑");
for(let i=0; i<4; i++) {
this.provinceInfo[i].value = pronId === '-1' ? 0 : Number((Math.random() * 10000).toFixed(0)).toLocaleString();//number.toLocaleString() 添加千分符
}
}
}
}
</script>
3. CSS部分
<style scoped>
.china-map {
width: 700px;
height: 500px;
background-color: #0B1F4F;
position: relative;
overflow: hidden;
}
/* 地图背景光圈 */
.china-map::before {
content: " ";
position: absolute;
left: 20%;
top: 15%;
width: 500px;
height: 500px;
border-radius: 50%;
background-image: radial-gradient(circle, #395AAC, #172E63, #122555, #0E2251);
}
/* 顶部省份名称 */
.title {
position: absolute;
top: 0;
left: 50%;
z-index: 2;
transform: translateX(-50%);
background-color: rgba(148, 188, 255, 0.5);
box-shadow: inset 0 0 8px 0 rgba(148, 188, 255, 1);
border-radius: 4px;
font-size: 16px;
font-weight: 400;
font-family: PingFangSC-Regular;
color: #FFFFFF;
letter-spacing: 3px;
line-height: 16px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
padding: 8px 20px;
}
/* 左上角-框体内容 */
.left {
position: absolute;
top: 0;
left: 0;
z-index: 2;
background-color: rgba(72, 107, 204, 0.1);
box-shadow: inset 0 0 4px 0 rgba(148, 188, 255, 1);
}
/* 去除ul默认样式 */
ul {
padding: 0;
margin: 0;
}
.left_ul {
width: 180px;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
font-family: PingFangSC-Regular;
font-size: 14px;
font-weight: 400;
line-height: 14px;
color: rgba(255, 255, 255, 0.5);
position: relative;
}
.left_ul::after {
content: " ";
position: absolute;
width: 1px;
height: 96px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: rgba(142, 171, 255, 0.2);
}
.left_li {
width: 90px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.left_li > span {
font-size: 20px;
color: var(--color, #94BCFF);
line-height: 20px;
display: block;
padding-bottom: 8px;
}
/* 地图尺寸 */
#chinaMapEle {
width: 700px;
height: 500px;
}
</style>