cesium文字实现避让功能

简介:

cesium项目上,当文字特别多的时候,互相遮挡比较严重

这个时候,可以通过“文字避让”来解决

原始文字如下图:

cesium文字实现避让功能_第1张图片使用避让功能后

cesium文字实现避让功能_第2张图片

实现思路:

1、把文字加载到cesium中

2、声明一个矩形集合,存储避让后的label的外包矩形,并提供了矩形相交的判断方法

3、获取每个文字对象在像素坐标系下的中心点、宽和高,并组装成矩形对象

4、对于步骤3中得到的矩形结果,与矩形集合的所有矩形进行相交判断

5、如果相交,则隐藏文字,并计算下一个;如果不相交,则加入到矩形集合,并显示文字

6、绑定相关事件,在每次camera改变的时候,重新计算

代码实现:

1、使用LabelCollection类来加载所有文字

const labelCol = scene.primitives.add(new Cesium.LabelCollection());
let oneLabel = labelCol.add({
  position: Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
  text: "Philadelphia",
});

2、创建矩形集合对象

let rectangleCollisionCheck = new Cesium.RectangleCollisionChecker();

3、获取每个“文字对象”在像素坐标系下的宽和高

注意:这里说的宽和高,是指label对象中所有文字占用的宽和高,不是单个字母的宽和高

比如:“abc”这个文字对象,是指abc三个字母共同占有的范围,而不是对单个a、b、c的分别计算

//1、
//oneLabel的中心点,在屏幕坐标系下的坐标
//其中,默认中心点是在文字左下角
//可以通过horizontalOrigin、verticalOrigin这2个参数来改变中心点在文字的左下角还是右上角
let ssPos = oneLabel.computeScreenSpacePosition(viewer.scene);

//2、
//拿到label对象中所有文字,在屏幕坐标系中占据的矩形大小
let boundingRectangle = Cesium.Label.getScreenSpaceBoundingBox(
oneLabel,
 ssPos
);

//3、
//boundingRectangle转换为Rectangle
//此时计算的Rectangle,并不是真实的wgs84坐标系
//其本质还是屏幕坐标系,只是在形式上转换为Rectangle类型
//这样方便rectangleCollisionCheck类的使用
let { x, y, width, height } = boundingRectangle;
const west = x;
const south = y;
const east = x + width;
const north = y + height;
const rectangle = new Cesium.Rectangle(west, south, east, north);

4、相交判断

//判断步骤3中计算的矩形,与“矩形集合”中的其他矩形是否相交
let isCollide = rectangleCollisionCheck.collides(rectangle)

5、相交结果处理

if (isCollide) {
  //和集合中的其他rectangle有交集    
  oneLabel.show = false;
  continue;
} else {
  //和集合中的其他rectangle没有交集
  oneLabel.show = true;
  rectangleCollisionCheck.insert(id, rectanglePretend);//当前rectangle添加进矩形集合
}

6、绑定事件

viewer.camera.moveEnd.addEventListener(function () {
    //rectangleCollisionCheck._tree.clear();
    //重新进行上述3、4、5的步骤
})

你可能感兴趣的:(Cesium,cesium,gis,避让,label)