echarts 地图点击弹窗溢出被遮挡问题处理

echarts yekong

vue 数据大屏 项目开发中,需要使用echarts渲染地图效果,为了数据展示以及效果美观,一般都会在鼠标点击地图的时候,在点击的位置显示一个弹窗用来展示数据,但是因为鼠标点击距离边界比较近,而弹窗又比较大,会导致弹窗不能完整的展示出来,会有一部分弹窗溢出边界被遮挡,导致无法完整显示,这时候我们就需要做一些处理了。

echarts 地图点击弹窗溢出被遮挡问题处理

解决思路

我们在鼠标点击的时候首先获取鼠标当前的坐标,并获取当前组件的宽和高,以及弹窗的宽和高,然后计算鼠标坐标加上弹窗的宽高是不是会超出div的边界,如果没有超出的话,就默认显示,如果超出了,就给一个预设的最大边界值。

关键代码

 myChart.on('click', function (params) {
        let data = myChart.convertFromPixel('geo', [params.event.event.offsetX, params.event.event.offsetY])
        // 判断是否超出x轴边界
        if (params.event.event.offsetX > (that.$refs.echartsBody.offsetWidth - 408)) {
          that.left = that.$refs.echartsBody.offsetWidth - 408
        } else {
          that.left = params.event.event.offsetX
        }
        // 判断是否超出y轴边界
        if (params.event.event.offsetY > (that.$refs.echartsBody.offsetHeight - 222)) {
          that.top = that.$refs.echartsBody.offsetHeight - 222
        } else {
          that.top = params.event.event.offsetY
        }
        that.name = params.data.name
        that.show = true
      })

完整代码

<template>
  <div class="item1" ref="echartsBody">
    <div class="centerMap2">
      <item :item="item" v-for="(item,index) in list" :key="index"></item>
    </div>
    <div class="centerMap" ref="centerMap">
    </div>
    <div class="map">
    </div>
    <div class="popWin" v-if="show" @click="show=false" :style="{left:left+'px',top:top+'px'}">
      <div class="popWins">
        <div class="titleInfos">
          <p class="cityName">地区信息</p>
        </div>
        <div class="popLine">
        </div>
        <div class="infoBody">
          <div class="infoItem">
            <div class="infoItemTitle">
              <img src="../assets/sudan.png" alt="">
              <span>{{ name }}</span>
            </div>
            <div class="infoItemDesc">对应的国家</div>
          </div>
          <div class="infoItem">
            <div class="infoItemTitle">3</div>
            <div class="infoItemDesc">对应数量</div>
          </div>
          <div class="infoItem">
            <div class="infoItemTitle">716</div>
            <div class="infoItemDesc">注册企业数量</div>
          </div>
          <div class="infoItem">
            <div class="infoItemTitle">植物源性食品、动物源...</div>
            <div class="infoItemDesc">主要产品</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>

import data from '../assets/data.json'
import * as echarts from "echarts"
import icon1 from '../assets/quan.png'

export default {
  name: "item1",
  data() {
    return {
      data,
      height: 0,
      width: 0,
      popShow: false,
      left: 0,
      top: 0,
      show: false,
      name: '',
      num: 10,
      iconData: [],
      list: []
    }
  },
  components: {},
  watch: {},
  mounted() {
    var that = this;
    const viewElem = document.body;
    // 监听窗口变化,重绘echarts
    const resizeObserver = new ResizeObserver(() => {
      setTimeout(() => {
        that.drawEcharts();
      }, 300)
    });
    resizeObserver.observe(viewElem);
  },

  methods: {
    drawEcharts() {
      var that = this;
      var chartDom = that.$refs.centerMap;
      var myChart = echarts.init(chartDom);
      myChart.clear()
      myChart.resize()
      var nameMap = '地图数据';
      var geoCoordMap = {};
      var mapData = [];
      // 图标数据
      echarts.registerMap(nameMap, this.data);
      var mapFeatures = echarts.getMap(nameMap).geoJson.features;
      myChart.hideLoading();
      var mapName = ''
      var serverdata = [{ // 地图块的相关信息
        type: 'map',
        name: '准入审核',
        map: nameMap,
        // zoom: 1.2,
        aspectScale: 0.85,
        z: 10,
        layoutCenter: ["50%", "50%"],
        layoutSize: '200%',
        itemStyle: {
          normal: {
            borderColor: '#93b3ea',
            borderWidth: 1,
            areaColor: '#2f73d9'
          },
          emphasis: {
            areaColor: '#416ef8',
            borderWidth: 0,
            label: {
              show: true,
              color: '#fff'
            },
          }
        },
        select: {
          label: {
            show: true,
            color: '#fff',
            normal: {
              show: true,
              textStyle: {
                fontSize: 14,
                fontWeight: 400,
                color: '#fff'
              }
            },
            emphasis: {
              textStyle: {
                fontSize: 14,
                fontWeight: 400,
                color: '#fff'
              }
            }
          },
          itemStyle: {
            areaColor: '#416ef8',
            borderWidth: 0,
          }
        },
        label: {
          show: false,
          normal: {
            show: false,
            textStyle: {
              fontSize: 14,
              fontWeight: 400,
              color: '#fff'
            }
          },
          emphasis: {
            show: false,
            textStyle: {
              fontSize: 14,
              fontWeight: 400,
              color: '#fff'
            }
          }
        },
        data: mapData
      }]

      mapFeatures.forEach(function (v, index) {
        // 地区名称
        mapData.push({
          name: v.properties.name,
          value: 10 * index
        });
        geoCoordMap[v.properties.name] = v.properties.center;
        mapName = mapName + (mapName ? ',' : '') + v.properties.name

      });
      that.iconData.forEach((type, index) => {
        var datamap = {
          type: 'scatter',
          tooltip: {
            show: true,
            formatter: function (params) {
              return params.data.name;
            }
          },
          name: type.name,
          coordinateSystem: 'geo',
          symbol: 'image://' + icon1,
          symbolSize: [26, 26],
          symbolOffset: [-0, -0],
          hoverAnimation: true,
          z: 101,
          data: [type]
        }
        serverdata.push(datamap)
      });
      var optionMap = {
        visualMap: [{
          min: 0,
          max: 100,
          show: false,
          right: 20,
          bottom: 0,
          realtime: true,
          calculable: true,
          seriesIndex: [0],
          inRange: {
            color: ['#e6edff', '#a8c3ff', '#12389b', '#2f73d9']
          }
        }],
        geo: {
          map: nameMap,
          show: false,
          aspectScale: 0.85,
          layoutCenter: ["50%", "50%"],
          layoutSize: '134%',
          roam: false,
          itemStyle: {
            normal: {
              areaColor: '#3391f8',
              shadowColor: '#3391f8',
              shadowBlur: 1,
              shadowOffsetX: 0,
              shadowOffsetY: 8,
            }
          },
          z: 0,
          label: {
            normal: {
              show: false
            },
            emphasis: {
              show: false
            }
          }
        },
        series: serverdata
      };
      myChart.clear()
      myChart.resize()
      myChart.setOption(optionMap);
      myChart.off('click')
      myChart.on('click', function (params) {
        let data = myChart.convertFromPixel('geo', [params.event.event.offsetX, params.event.event.offsetY])
        // 判断是否超出x轴边界
        if (params.event.event.offsetX > (that.$refs.echartsBody.offsetWidth - 408)) {
          that.left = that.$refs.echartsBody.offsetWidth - 408
        } else {
          that.left = params.event.event.offsetX
        }
        // 判断是否超出y轴边界
        if (params.event.event.offsetY > (that.$refs.echartsBody.offsetHeight - 222)) {
          that.top = that.$refs.echartsBody.offsetHeight - 222
        } else {
          that.top = params.event.event.offsetY
        }
        that.name = params.data.name
        that.show = true
      })
    }
  },
}
</script>

<style lang="scss" scoped>
.item1 {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
}

.map {
  //background: url("../../../../../assets/centerMap.png") center center no-repeat;
  //background-size: 1024px 783px;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
  margin: 0 auto;
  position: absolute;
  z-index: 0;

  img {
    height: 100%;
    max-width: 100%;
    max-height: 100%;
  }
}

.centerMap {
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
  top: 0;
}

.centerMap2 {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 13;
  top: 0;
  pointer-events: none;
}

.popWin {
  position: absolute;
  left: 0;
  top: 0;
  background: url("../assets/popBg.png") no-repeat;
  background-size: 100% 100%;
  width: 408px;
  height: 222px;
  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 {
    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;
  }
}

.infoBody {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
  flex-direction: row;
  align-content: flex-start;
  width: 100%;

  .infoItem {
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
    flex-wrap: nowrap;
    flex-direction: column;
    align-content: flex-start;
    margin-left: 30px;
    width: 40%;
    height: 80px;

    .infoItemTitle {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      margin-top: 20px;
      align-content: flex-start;
      font-size: 16px;
      font-family: MicrosoftYaHei;
      font-weight: bold;
      color: #FFFFFF;
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;

      img {
        margin-right: 5px;
      }
    }

    .infoItemDesc {
      font-size: 14px;
      font-family: MicrosoftYaHei;
      font-weight: 400;
      color: #FFFFFF;
      opacity: 0.6;
    }
  }
}
</style>

喜欢