cesium文字实现避让功能

简介:

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

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

原始文字如下图:

使用避让功能后

实现思路:

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的步骤
})

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
要使用Cesium实现闸门开启功能,可以使用以下代码: ```javascript const viewer = new Cesium.Viewer('cesiumContainer'); // 创建一个矩形实体(表示闸门) const rectangle = viewer.entities.add({ name: 'Gate', rectangle: { coordinates: Cesium.Rectangle.fromDegrees(115.0, 39.0, 117.0, 41.0), material: Cesium.Color.RED.withAlpha(0.5), outline: true, outlineColor: Cesium.Color.BLACK } }); // 定义闸门当前的高度 let gateHeight = 0; // 创建一个滑动条控件,用于控制闸门高度 const slider = document.getElementById('slider'); slider.oninput = function() { // 更新闸门高度 gateHeight = parseFloat(slider.value); // 更新闸门实体的高度 rectangle.rectangle.height = gateHeight; // 刷新场景 viewer.scene.requestRender(); } ``` 在上面的代码中,我们首先创建了一个 Cesium 的 Viewer 对象,然后创建了一个矩形实体,表示闸门。接着,我们定义了一个`gateHeight`变量,用于记录闸门当前的高度。然后,我们创建了一个滑动条控件,用于控制闸门的高度。当滑动条的值发生变化时,我们会更新`gateHeight`变量,并更新闸门实体的高度。最后,我们调用`viewer.scene.requestRender()`方法刷新场景,以显示更新后的闸门高度。 需要注意的是,上述代码中的`slider`元素需要在 HTML 中定义好。例如,可以在 HTML 中添加以下代码: ```html <input type="range" min="0" max="1000" value="0" class="slider" id="slider"> ``` 其中,`min`和`max`属性分别表示滑动条的最小值和最大值,`value`属性表示滑动条的初始值。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈地图

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值