首页 前端知识 Vue Echarts实现全国地图下钻(地图钻取) 标记点位 弹窗提示

Vue Echarts实现全国地图下钻(地图钻取) 标记点位 弹窗提示

2024-01-25 11:01:15 前端知识 前端哥 406 798 我要收藏

        最近项目需要开发大屏,要实现全国地图下钻,并且根据不同状态标记点位,点击弹窗显示当前点击省市区的列表信息,弹窗位置根据点击位置获取,记录一下。

        其中地图数据用了阿里云数据可视化平台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>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/340.html
标签
echartsvue.js
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!