最近项目需要开发大屏,要实现全国地图下钻,并且根据不同状态标记点位,点击弹窗显示当前点击省市区的列表信息,弹窗位置根据点击位置获取,记录一下。
其中地图数据用了阿里云数据可视化平台DataV.GeoAtlas,地址:地图数据
最终效果如下所示:
不废话,直接上代码:
<template>
<div class="echart-bmap_wrapper">
<div class="btn">
<el-button type="primary" @click="goBack" size="mini">全国</el-button>
</div>
<div class="bmap-box" id="bmapChartBox"></div>
<div class="popWin" v-if="popShow" :style="{ left: popLeft + 'px', top: popTop + 'px' }">
<div class="popWins">
<div class="titleInfos">
<p class="cityName">{{ name }}工厂</p>
<span class="pop_close" @click="popShow = false">关闭</span>
</div>
<div class="popLine"> </div>
<div class="infoBody">
<basic-table class="homeTable" :TableHeaderList="TableHeaderList" :tableData="tableData" :hasPagination="false" :tableHeight="220" :rowHeight="20"></basic-table>
</div>
</div>
</div>
</div>
</template>
<script>
import basicTable from "@/components/basicComponents/basicTable.vue"; // 公用table组件
import * as echarts from 'echarts';
import * as basicDataApi from '@/api/basicData.js'//基础资料接口
var provinceMapData = require('./mapData/provinceMapData.json');//全国地图省份数据,自己取上面地址取
export default {
components: { basicTable },
name: 'echartBmap',
data() {
return {
pointData: [],//标点信息,需要动态获取,初始化全国地图的点位
provinceCodeData: [],//处理后全国省份数据带code
mapStack: [],//存储一下地图历史记录,用于返回
nowChooseData: [],//当前选择的数据源
option: {
tooltip: {
trigger: 'item',
},
geo: [{
map: 'js',
aspectScale: 0.9,
roam: true, // 是否允许缩放
zoom: 1.2, // 默认显示级别
center: [116.405285, 39.904989], // 地图中心点坐标
label: {
normal: {
show: true, // 是否地图显示区域的文字,各省市的名字
textStyle: {
color: '#fff'
}
},
emphasis: {
textStyle: {
color: '#fff'
}
}
},
itemStyle: {
// 区域颜色
areaColor: {
type: 'radial',
x: 0.7,
y: 0.5,
r: 0.4,
// 渐变效果
colorStops: [{
offset: 0,
color: '#24cff4' // 0% 处的颜色
}, {
offset: 0.5,
color: '#2babd9' // 50% 处的颜色
}, {
offset: 1,
color: '#236bb2' // 100% 处的颜色
}],
global: false // 缺省为 false
},
emphasis: {
areaColor: '#56dcf9', // 鼠标移入区域背景颜色
borderWidth: 0
},
borderColor: '#37C1FD',
borderWidth: 2
},
emphasis: {
itemStyle: {
areaColor: '#0160AD'
},
label: {
show: 1,
color: '#fff'
}
},
zlevel: 3
}],
series: [{
type: 'effectScatter',
coordinateSystem: 'geo',
// symbol: 'diamond',
showEffectOn: 'render',
rippleEffect: {
period: 10,
scale: 6,
brushType: 'fill'
},
zlevel: 10, // 这里是关键,一定要放在 series中,显示层级,
hoverAnimation: true,
itemStyle: {
normal: {
// 点的颜色可以根据 params 参数里面的值去设定不通的颜色
color: function (params) {
if (params.name == '7300网关') {
return 'red';
}
if (params.name == '700网关') {
return 'yellow';
}
if (params.name == '5300网关') {
return 'green';
}else{
return 'pink';
}
},
shadowBlur: 10,
shadowColor: '#333'
}
},
data: [] // 点的数据,包含经纬度
}]
},
// 测试标点数据
gatewayPointData: {
'黑龙江省': [
{
name: '7300网关',
value: [126.642464, 45.756967]
},
],
'哈尔滨市': [
{
name: '7300网关',
value: [126.957401, 45.454116]
},
{
name: '700网关',
value: [126.394846, 45.778706]
},
{
name: '5300网关',
value: [126.606415, 45.807463]
},
{
name: '300网关',
value: [126.483958, 45.876779]
},
{
name: '2300网关',
value: [126.785501, 45.739871]
}
],
},
popShow: false,//弹窗是否显示
popLeft: 0,//弹窗X轴距离
popTop: 0,//弹窗Y轴距离
name: '',//当前点击省份
TableHeaderList: [],//table表头数据
tableData: [],//table数据
};
},
mounted() {
// 渲染地图
this.drawMap(provinceMapData, 0, [126.82862, 49.296976]);
this.getProvinceCode();//处理全国省份数据
// 初始化mapStack数据,默认全国数据
this.mapStack = []
this.mapStack.push(provinceMapData)
},
methods: {
// 处理全国省份数据
getProvinceCode() {
provinceMapData.features.forEach(item => {
this.provinceCodeData.push({
name: item.properties.name,
coordinateCenter: item.properties.center,
cityCode: item.properties.adcode
})
});
},
// 返回全国
goBack() {
this.popShow = false
this.mapStack = []
this.mapStack.push(provinceMapData)
this.drawMap(provinceMapData, 0, [126.82862, 49.296976]);
},
// 设置地图配置信息
setMapCenterZoomData(data, zoom, center) {
this.option.series[0].data = data;
this.option.geo[0].zoom = zoom;
this.option.geo[0].center = center;
if (this.mapStack.length <= 1) {//设置图层位置
this.option.geo[0].layoutSize = '100%';
this.option.geo[0].layoutCenter = ['85%', '20%'];
} else {
this.option.geo[0].layoutSize = '';
this.option.geo[0].layoutCenter = [];
}
},
// 渲染地图
drawMap(json, type = 0, city) {
// 防止echarts重复
if (document.getElementById('bmapChartBox') == null) {
return
}
echarts.dispose(document.getElementById('bmapChartBox'))
// 防止echarts重复
this.echarts = echarts;
this.dom = document.getElementById('bmapChartBox');
this.myChart = this.echarts.init(this.dom);
this.echarts.registerMap('js', json);
if (type == 1) {//地图点击进入
this.pointData = this.gatewayPointData[city];//标点数据
if(this.pointData){//如果有标点数据
this.setMapCenterZoomData(this.pointData, 1.2, this.pointData[0].value);
}else{//如果没有标点数据
// 使用测试数据 - 把当前选择地图数据作为标点数据
this.nowChooseData.forEach(i=>{
i.value = i.coordinateCenter
})
this.pointData = this.nowChooseData
var center = this.nowChooseData[0].coordinateCenter;//取当前选择省市区第一个数据的坐标
this.setMapCenterZoomData(this.pointData, 1.2, center);
}
} else {//初始化进入
this.myChart.clear();
this.setMapCenterZoomData([], 1, [126.82862, 49.296976]);
}
this.myChart.setOption(this.option);
this.myChart.off('click');
this.myChart.on('click', (param) => {
// 点击弹窗方法
// 点击获取经纬度
let data = this.myChart.convertFromPixel('geo', [param.event.event.offsetX, param.event.event.offsetY])
this.popLeft = param.event.event.offsetX
this.popTop = param.event.event.offsetY
// 获取城市名称 list下的name值
this.name = param.name
this.popShow = true
// 点击弹窗方法
if (param.componentType == "geo") {//点击地图
} else {//点击标点不允许下钻
return;
}
// 省市区三级后跳出点击
if (this.mapStack.length >= 3) {
this.$notify({
message: '没有更多啦!',
type: 'warning',
duration: 2000
});
return;
}
const city = param.name;
// 获取点击对应的cityCode
var cityCode = ''
if (this.mapStack.length <= 1) {//初始化全国省份数据
this.provinceCodeData.forEach(i => {
if (i.name == city) {
cityCode = i.cityCode
}
})
} else {//选择后的市区数据
this.nowChooseData.forEach(i => {
if (i.name == city) {
cityCode = i.cityCode
}
})
}
this.getHomeMapData(city, cityCode)
});
},
// 获取基础配置数据
getHomeMapData(city, cityCode) {
var cityMapData //当前选中的省市区地图数据
// 请求数据
var data
if( cityCode == 710000){//台湾特殊处理,后缀没有_full
data = {
code: cityCode
}
}else{
data = {
code: cityCode + '_full'
}
}
//通过接口获取点击下钻的地图数据
basicDataApi.getHomeMapDataApi(data).then(res => {
if (res) {
cityMapData = res
// 让历史数据一直保持在3个之内,存储显示过的地图数据
if (this.mapStack.length < 3) {
this.mapStack.push(cityMapData);
}
this.nowChooseData = []
cityMapData.features.forEach(item => {
this.nowChooseData.push({
name: item.properties.name,
coordinateCenter: item.properties.center,
cityCode: item.properties.adcode
})
});
cityMapData && this.myChart.clear();
cityMapData && this.drawMap(cityMapData, 1, city);
this.getTableData();//获取table数据
}
}).catch((err) => {
this.$message(err.message);
});
},
//获取table数据
getTableData(){
this.TableHeaderList = [
{
FieldDisplayName: "网关名称",
// ColumnWidth: 120,
Field: "gatewayName",
IsShow: true,
},
{
FieldDisplayName: "状态",
// ColumnWidth: 120,
Field: "status",
IsShow: true,
QuerySource:"GatewayStatus",
},
{
FieldDisplayName: "设备总数",
// ColumnWidth: 120,
Field: "gatewayNum",
IsShow: true,
},
{
FieldDisplayName: "测点总数",
// ColumnWidth: 120,
Field: "pointNum",
IsShow: true,
},
]
this.tableData = [
{ num: 1, gatewayName: '网关1', status: '1', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '2', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '3', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '4', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '5', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '1', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '2', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '3', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '4', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '1', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '2', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '3', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '1', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '2', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '3', gatewayNum: '321', pointNum: '442', },
{ num: 1, gatewayName: '网关1', status: '2', gatewayNum: '321', pointNum: '442', },
]
},
}
};
</script>
<style lang="scss" scoped>
.echart-bmap_wrapper {
position: relative;
.btn {
position: absolute;
left: 20px;
top: 20px;
z-index: 1;
}
.bmap-box {
width: 100%;
height: 90vh;
}
.popWin {
position: absolute;
left: 0;
top: 0;
background: #00305c;
background-size: 100% 100%;
width: 408px;
height: 300px;
z-index: 100;
.popLine {
width: 340px;
height: 1px;
background: linear-gradient(90deg, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%);
opacity: 0.3;
margin-left: 30px;
}
.titleInfos {
text-align: center;
margin-left: 30px;
font-size: 22px;
font-family: YouSheBiaoTiHei;
font-weight: 400;
color: #00FDFE;
height: 50px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
.pop_close{
color:#bbb;
cursor: pointer;
padding:5px;
font-size:12px;
position: absolute;
top: 5px;
right: 10px;
}
}
}
.infoBody {
width: 100%;
padding:3%;
.homeTable{
border:1px solid #0376ae;
border-radius: 10px;
}
}
.infoBody ::v-deep .plTableBox .el-table .cell.el-tooltip{
border-bottom: 1px solid #086896;
}
.infoBody ::v-deep .el-table, .el-table__expanded-cell {
background-color: transparent;
}
.infoBody ::v-deep .el-table tr {
// background-color: transparent!important;
background-color: #0b4d73;
}
.infoBody ::v-deep .el-table--enable-row-transition .el-table__body td, .el-table .cell{
background-color: transparent;
}
.el-table::before {//去除底部白线
left: 0;
bottom: 0;
width: 100%;
height: 0px;
}
.infoBody ::v-deep .plTableBox .el-table .el-table__header th{
background-color: transparent;
}
.infoBody ::v-deep .plTableBox .el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: rgba(0,77,167,1);
}
.infoBody ::v-deep .plTableBox .el-table--border td,.infoBody ::v-deep .plTableBox .el-table--border th,.infoBody ::v-deep .plTableBox .el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{
border: none;
color:#4daad3
}
.infoBody ::v-deep .plTableBox .el-table--medium td{
padding: 0;
}
.infoBody ::v-deep .plTableBox .el-table__header-wrapper{
background-color: transparent;
}
.infoBody ::v-deep .plTableBox .el-table--striped .el-table__body tr.el-table__row--striped td{
background-color: #103c5c;
}
}
</style>