大屏缩放后,百度地图点击点位不准

864 阅读2分钟

一、问题描述及原因分析

大屏按照1920:1080的设计稿设计,前端一般采用对最外层组件使用transfrom:scale的方式对整个容器进行缩放来实现。但是对于百度地图,猜测其有自己的一套坐标体系,在点击地图时,会出现点击位置不准确的问题,导致想要对事件监听并做操作时,操作事件无法正常进行

二、问题解决方案

2.1前提

需求是在百度地图点击时,在点击处展示该区域的某项数据。本文以百度地图绘制杭州市地图为例。地图绘制时,是通过遍历杭州市的每个区域,为其添加背景色和边界色绘制地图的,在绘制的过程中,需给每块区域的Ploygon的实例对象添加一些数据,以供后面鼠标点击时使用,并将每块区域对象添加到一个数组中,以供后续遍历。

2.2准备工具

在线地图需引入对应的BMapGLLib文件及GeoUtils文件,离线地图需保证有前述文件。注意:GeoUtils.js文件主要是在BMapGlLib上添加各种方法,该文件需直接去github上下载并引入

<script src="//mapopen.bj.bcebos.com/github/BMapGLLib/DrawingManager/src/DrawingManager.min.js"></script>
<script src="./js/GeoUtils.js"></script>

2.3 关键代码实现

map.on('click', (params) => {
  // 1.获取缩放比例
  const xScale = localStorage.getItem('xScale')
  const yScale = localStorage.getItem('yScale')
  // 2.获取点击时的像素坐标,还原缩放并转为经纬度
  const { x, y } = params.pixel
  const pixel2 = new BMapGL.Pixel(x / xScale, y / yScale)
  const point = map.pixelToPoint(pixel2)
  // 3.判断点是否在多边形内,以获得点击项的数据
  plgArr.forEach(item => {
    if(BMapGLLib.GeoUtils.isPointInPolygon(point, item)) {
      const name = item.customData.name
      const target = this.heatData.find(item => item.name === name)
      this.coverData = {
        name: target.name,
        value: Math.ceil(Number(target.value) * 100)
      }
    }
  })
  // 4.展示图表时,定位的位置也需经过偏移量的转化
  const currentX = params.pixel.x / xScale
  const currentY = params.pixel.y / yScale
  this.coverEchartStyle = {
    left: currentX + 30 + 'px',
    top: currentY + 30 + 'px'
  }
  this.$nextTick(() => {
    this.isShowCoverChart = true
    this.$nextTick(() => {
      //地图点击时在点击附近处展示Echarts弹窗
      this.$refs.coverChart.openDialog(this.coverData)
    })
  })
})
//后发现改方法只针对在线地图使用,离线地图不适用的方法后续还需探究。
// 后续优化方法 如果地图上有**区这种覆盖物的,那么可以将监听事件改为对覆盖物的监听。这样就可以省略第三步,并且数据改为根据当前点击事件的参数中获得
label.on('click', (params) => {
    const xScale = localStorage.getItem('xScale')
    const yScale = localStorage.getItem('yScale')
    const target = this.heatData.find(item => item.name === params.currentTarget.content)
      this.coverData = {
        name: target.name,
        value: Math.ceil(Number(target.value) * 100)
      }
    const currentX = params.pixel.x / xScale
    const currentY = params.pixel.y / yScale
    this.coverEchartStyle = {
      left: currentX + 30 + 'px',
      top: currentY + 30 + 'px'
    }
    this.$nextTick(() => {
      this.isShowCoverChart = true
      this.$nextTick(() => {
        this.$refs.coverChart.openDialog(this.coverData)
      })
    })
})