低代码大屏设计: cesium地图外层容器transform后, 地图点击位置偏移严重

1,751 阅读2分钟

前言

在低代码大屏设计器中, cesium地图被设计成一个可拖拽到画布中的组件. 为了适应不同的屏幕分辨率, cesium地图的外层容器加了transform属性, 该属性将外层容器拉伸, 自动填满整个屏幕.

但是, 问题来了. 外层容器transform之后, 导致cesium地图也被强行拉伸, 在地图上进行测量绘制时, 会发生严重的位置偏差.

无论是翻墙查找, 还是使用chatgpt, 关于这个问题的解决方案有倒是有, 可惜要么收费, 要么只贴了简单的代码, 连注释说明都没有.

基于以上原因, 我将我的解决方案, 详细地分享给大家.

正文

如何解决点击位置偏移的问题呢?

  • 若cesium地图是外部js引入, 则只需更改ScreenSpaceEventHandler.js里的getPosition函数
  • 若cesium地图是npm包方式引入, 则需创建自定义CustomScreenSpaceEventHandler.js文件, 替换cesium里的ScreenSpaceEventHandler.js文件

cesium地图外部js引入

我们需找到ScreenSpaceEventHandler.js里的getPosition函数, 如下图

image.png

getPosition函数替换为如下代码

function getPosition(screenSpaceEventHandler, event, result) {
  var element = screenSpaceEventHandler._element
  var fa = element.offsetWidth / element.getBoundingClientRect().width
  var fa1 = element.offsetHeight / element.getBoundingClientRect().height
  if (element === document) {
    result.x = event.clientX * fa
    result.y = event.clientY * fa1
    return result
  }

  var rect = element.getBoundingClientRect()
  result.x = (event.clientX - rect.left) * fa
  result.y = (event.clientY - rect.top) * fa1
  return result
}

通过代码对比, 我们可以看出, 替换后的代码里面加入了宽高对比因子fa fa1, 返回的经纬度需乘以该因子, 才能解决点击位置偏移的问题

cesium地图npm包引入

  1. 创建自定义CustomScreenSpaceEventHandler.js文件, 代码如下图所示:
import {
  AssociativeArray,
  Cartesian2,
  defaultValue,
  defined,
  destroyObject,
  DeveloperError,
  FeatureDetection,
  getTimestamp,
  KeyboardEventModifier,
  ScreenSpaceEventType
} from 'cesium'

function getPosition(screenSpaceEventHandler, event, result) {
  var element = screenSpaceEventHandler._element
  var fa = element.offsetWidth / element.getBoundingClientRect().width
  var fa1 = element.offsetHeight / element.getBoundingClientRect().height
  if (element === document) {
    result.x = event.clientX * fa
    result.y = event.clientY * fa1
    return result
  }

  var rect = element.getBoundingClientRect()
  result.x = (event.clientX - rect.left) * fa
  result.y = (event.clientY - rect.top) * fa1
  return result
}
...

省略的代码与ScreenSpaceEventHandler.js里的代码一模一样, 我们只需替换getPosition函数即可.

  1. 全局搜索所有引入ScreenSpaceEventHandler代码的文件, 将ScreenSpaceEventHandler替换为CustomScreenSpaceEventHandler, 如下图所示

image.png

image.png

  1. 再次打开地图, 点击地图进行测量, 发现问题已被解决, 完结撒花~~~

尾声

为了解决该问题, 杀死了我的不少脑细胞. 从中我发现国内技术文章收费的问题比较严重, 希望大家秉持着技术开源、无国界的想法, 将技术代码或解决方案开源分享, 因为唯有如此, 个人的发展才能走得更远.