实现效果如下图
使用工具:
- 引入echarts
- 使用DataV.GeoAtlas地理小工具系列 (aliyun.com)获取中国及下各省份地图数据 项目地址lisa25/echarts-map - 码云 - 开源中国 (gitee.com)
项目目录结构
- country中存放中国json数据
- province中存放省份json数据
- china-data.js为各省份信息,地图下钻时用于获取对应省份json文件名
南海群岛放在右下角框问题: 在geo中配置regions
geo: {
show: true,
map: mapName,
regions: [
{
name: "南海诸岛",
value: 0,
itemStyle: {
normal: {
opacity: 0,
label: {
show: false
}
}
}
}
],
roam: false,
top: "12%",
// left: "11%",
layoutCenter: ["30%", "30%"],
zoom: 1.2,
aspectScale: 1.11,
label: {
normal: {
show: false
},
emphasis: {
show: false
}
},
itemStyle: {
normal: {
opacity: 1, //图形透明度 0 - 1
borderColor: "#09a5df00", //图形的描边颜色
borderWidth: 2, //描边线宽。为 0 时无描边。
borderType: "solid", //柱条的描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'。
areaColor: "#17395b" //图形的颜色 #eee
},
emphasis: {
borderColor: "#09a5df00",
borderWidth: 2,
areaColor: "#17395b",
label: {
show: false
}
}
},
tooltip: {
formatter: o => {
return
}
}
},
海南省隐藏市级线 删掉中国json数据中海南省数据中的市级数据即可
关于地图点击事件是监听地图的click事件
this.eMap.on("click", e => {
let mapData = chinaData.find(item => item.name == e.name);
if (mapData) {
this.mapTitle = e.name;
this.mapName = mapData.mapName;
this.geoJson = require(`./province/${this.mapName}.json`);
this.initMap(this.mapName, this.geoJson);
}
});
完整vue文件如下:
<template>
<div class="mapBox">
<div id="eMap" style="width: 79%; height: 95%"></div>
<div class="mapRouter">
<span class="back" @click="backChina">中国</span>
<span v-if="mapTitle != ''">/</span>
<span class="nextMap">{{ mapTitle ? mapTitle : "" }}</span>
</div>
</div>
</template>
<script>
import china from "./country/china.json";
import chinaData from "./china-data.js";
import * as echarts from "echarts";
import micon_jifang from './img/micon_jifang.svg'
import micon_offline from './img/micon_offline.svg'
import micon_online from './img/micon_online.svg'
import { debounce } from '@/utils';
export default {
data () {
return {
eMap: null,
china: china,
mapOption: {},
mapData: [
{
lat: 28.676493,
lng: 115.892151,
parent: "江西省",
name: "兴图新科",
type: "jifang",
project: "兴图新科",
cabinetNum: 3,
deviceNum: 30,
onlineDevice: "20/30",
offlineDevice: "1/30",
inFlow: 30,
outFlow: 20,
position: "江西省南昌市"
},
{
lat: 34.757975,
lng: 113.665412,
parent: "河南省",
name: "视频传输网关",
project: "兴图新科",
ip: "11.15.83.10",
position: "河南省郑州市",
deviceStatus: 1,
unitStatus: "15/16",
type: "fdevice"
},
{
lat: 30.659462,
lng: 104.065735,
parent: "四川省",
name: "四川省机房",
type: "odevice"
},
{
adcode: "500000",
people_count_2010: 28458101,
lat: 29.533155,
lng: 106.504962,
parent: "重庆市",
name: "重庆市机房",
type: "odevice"
}
],
mapTitle: "",
mapName: "",
geoJson: null
};
},
mounted () {
this.initMap();
this.eMap.on("click", e => {
let mapData = chinaData.find(item => item.name == e.name);
if (mapData) {
this.mapTitle = e.name;
this.mapName = mapData.mapName;
this.geoJson = require(`./province/${this.mapName}.json`);
this.initMap(this.mapName, this.geoJson);
}
});
this.__resizeHandler = debounce(() => {
if (this.eMap) {
this.eMap.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
},
beforeDestroy () {
if (this.eMap) {
echarts.dispose(this.eMap);
this.eMap = null;
}
},
methods: {
initMap (mapName = "china", geoJson = china) {
this.eMap = echarts.init(document.querySelector("#eMap"));
echarts.registerMap(mapName, geoJson);
this.mapOption = {
// 提示框组件(可以设置在多种地方)
tooltip: {
show: true, //是否显示提示框组件,包括提示框浮层和 axisPointer。
trigger: "item", //触发类型。item,axis,none
enterable: true, //鼠标是否可进入提示框浮层中,默认为false,
showContent: true, //是否显示提示框浮层
triggerOn: "mousemove", //提示框触发的条件(mousemove|click|none)
showDelay: 10, //浮层显示的延迟,单位为 ms,默认没有延迟,也不建议设置。在 triggerOn 为 'mousemove' 时有效。
textStyle: {
color: "white",
fontSize: 12
},
confine: true,
hideDelay: 10, //浮层隐藏的延迟
formatter: o => {
if (o.value) {
let data = o.data;
if (data.type == "jifang") {
return `<div class="jifang_mapInfo">
<div class="mapInfo_title">
<div class="title_icon"></div>
<div class="text overText" title="${data.project}">
${data.project}
</div>
</div>
<div class="mapInfo_content">
<div>
<div class="width8">机柜数量</div>
<div class="width14">${data.cabinetNum} 个</div>
</div>
<div>
<div class="width8">设备数量</div>
<div class="width14">${data.deviceNum} 台</div>
</div>
<div>
<div class="width8">在线设备</div>
<div class="width14">${data.onlineDevice}</div>
</div>
<div>
<div class="width8">异常设备</div>
<div class="width14">${data.offlineDevice}</div>
</div>
<div>
<div class="width8">输入流量</div>
<div class="width14">${data.inFlow} Gbps</div>
</div>
<div>
<div class="width8">输出流量</div>
<div class="width14">${data.outFlow} Gbps</div>
</div>
<div>
<div class="width8">机房位置</div>
<div class="width14" title="${data.position}">${data.position
}</div>
</div>
</div>
</div>`;
} else {
return `<div class="device_mapInfo">
<div class="mapInfo_title">
<div class="title_icon"></div>
<div class="text overText" title="${data.name}">
${data.name}
</div>
</div>
<div class="mapInfo_content">
<div>
<div class="width8">所属项目</div>
<div class="width14" title="${data.project}">${data.project
}</div>
</div>
<div>
<div class="width8">设备IP</div>
<div class="width14">${data.ip}</div>
</div>
<div>
<div class="width8">设备位置</div>
<div class="width14" title="${data.position}">${data.position
}</div>
</div>
<div>
<div class="width8">设备状态</div>
<div class="width14">${data.deviceStatus == 1 ? "正常运行" : "异常停止"
}</div>
</div>
<div>
<div class="width8">单元状态</div>
<div class="width14">${data.unitStatus}</div>
</div>
</div>
</div>`;
}
}
},
backgroundColor: "#00a2e300", //提示框浮层的背景颜色。
alwaysShowContent: true,
transitionDuration: 1 //提示框浮层的移动动画过渡时间,单位是 s,设置为 0 的时候会紧跟着鼠标移动。
},
//地理坐标系组件。地理坐标系组件用于地图的绘制,支持在地理坐标系上绘制散点图,线集。
geo: {
show: true,
map: mapName,
regions: [
{
name: "南海诸岛",
value: 0,
itemStyle: {
normal: {
opacity: 0,
label: {
show: false
}
}
}
}
],
roam: false,
top: "12%",
// left: "11%",
layoutCenter: ["30%", "30%"],
zoom: 1.2,
aspectScale: 1.11,
label: {
normal: {
show: false
},
emphasis: {
show: false
}
},
itemStyle: {
normal: {
opacity: 1, //图形透明度 0 - 1
borderColor: "#09a5df00", //图形的描边颜色
borderWidth: 2, //描边线宽。为 0 时无描边。
borderType: "solid", //柱条的描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'。
areaColor: "#17395b" //图形的颜色 #eee
},
emphasis: {
borderColor: "#09a5df00",
borderWidth: 2,
areaColor: "#17395b",
label: {
show: false
}
}
},
tooltip: {
formatter: o => {
return
}
}
},
//系列列表。每个系列通过 type(map, scatter, bar, line, gauge, tree.....) 决定自己的图表类型
series: [
{
map: mapName,
type: "scatter",
coordinateSystem: "geo",
symbolSize: 0,
silent: "none",
data: [],
itemStyle: {
normal: {
opacity: 1, //图形透明度 0 - 1
borderColor: "#09a5df5f", //图形的描边颜色
borderWidth: 2, //描边线宽。为 0 时无描边。
borderType: "solid", //柱条的描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'。
areaColor: "#17395b" //图形的颜色 #eee
}
}
},
{
map: mapName,
type: "map",
top: "8%",
// left: "10.2%",
zoom: 1.2, //当前视角的缩放比例。
aspectScale: 1.11, //这个参数用于 scale 地图的长宽比。geoBoundingRect.width / geoBoundingRect.height * aspectScale
roam: false, //是否开启鼠标缩放和平移漫游。默认不开启
layoutCenter: ["30%", "30%"],
label: {
show: false,
textStyle: {
color: "white",
fontSize: 12,
backgroundColor: "" //文字背景色
}
},
itemStyle: {
normal: {
borderColor: "#0fc4d890", //图形的描边颜色
borderWidth: 1.5, //描边线宽。为 0 时无描边。
borderType: "solid", //柱条的描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'。
areaColor: "#073051", //图形的颜色 #eee
label: {
show: false,
textStyle: {
color: "white",
fontSize: 14
}
}
},
//鼠标移入时
emphasis: {
disabled: true,
borderColor: "#005b89",
borderWidth: 1,
areaColor: "#098196",
label: {
color: "#fff"
}
},
effect: {
show: true,
shadowBlur: 10,
loop: true
}
},
},
{
type: "scatter",
coordinateSystem: "geo",
//自定义图片的 位置(lng, lat)
data: this.mapData.map((item, index) => {
if (mapName == "china" || item.parent == this.mapTitle) {
let symbol = "image://";
let symbolSize = [];
let symbolOffset = [];
switch (item.type) {
case "jifang":
symbol = symbol + micon_jifang;
symbolSize = [40, 50];
symbolOffset = [0, -25];
break;
case "fdevice":
symbol = symbol + micon_online;
symbolSize = [40, 50];
symbolOffset = [0, -25];
break;
case "odevice":
symbol = symbol + micon_offline;
symbolSize = [40, 50];
symbolOffset = [0, -25];
break;
}
item.value = [item.lng, item.lat];
item.symbolSize = symbolSize;
item.symbolOffset = symbolOffset;
item.symbol = symbol;
return item;
}
})
}
]
};
this.eMap.setOption(this.mapOption);
},
backChina () {
this.initMap("china", china);
this.mapTitle = "";
}
}
};
</script>
<style lang="scss" scoped>
.mapBox {
width: calc(100% - 40px);
height: calc(100% - 40px);
display: flex;
justify-content: center;
align-items: center;
.mapRouter {
position: absolute;
top: 50px;
right: 0px;
color: #fff;
font-size: 16px;
font-weight: 700;
cursor: pointer;
.back:hover {
color: #27fffc;
}
}
}
</style>
<style>
.jifang_mapInfo {
width: 190px;
height: 238px;
background: url("./img/jifang_bg.png") no-repeat;
background-size: 100% 100%;
margin: 0;
padding: 12px;
}
.device_mapInfo {
width: 190px;
height: 182px;
background: url("./img/device_bg.png") no-repeat;
background-size: 100% 100%;
margin: 0;
padding: 12px;
}
.mapInfo_title {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 27px;
padding: 0 4px;
background-image: linear-gradient(
90deg,
rgba(68, 253, 251, 0.16) 0%,
rgba(68, 253, 251, 0.01) 100%
);
}
.mapInfo_title .title_icon {
display: inline-block;
width: 16px;
height: 17px;
background: url("./img/panel_icon.png") no-repeat;
background-size: 100% 100%;
}
.mapInfo_title .text {
width: 138px;
}
.mapInfo_content {
width: 100%;
height: calc(100% - 30px);
}
.mapInfo_content .width8 {
display: inline-block;
width: 30%;
font-size: 12px !important;
margin-left: 6px;
margin-top: 8px;
color: #c5d0d4;
}
.mapInfo_content .width14 {
display: inline-block;
width: 70%;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #27fffc;
vertical-align: bottom;
}
</style>