• SuperMap iClient3D 11i (2023) SP1 for Cesium之移动实体对象


     作者:nannan

    目录

    前言

    一、代码思路

    1.1 绘制面实体对象

    1.2 鼠标左键按下事件

    1.3 鼠标移动事件

    1.4 鼠标左键抬起事件

    二、运行效果

    三、注意事项


    前言

           SuperMap 官网三维前端范例 编辑线面,可以对面实体对象的节点进行增加、删除以及修改位置。那可不可以整个线/面对象选中后鼠标拖动,使该面对象的整体位置随着鼠标的移动而移动呢?目前客户这种需求是为了项目上可以实时调整面的区域,方便后端出图。下面和小编一起来看看该功能实现的过程及效果。

    一、代码思路

    1.1 绘制面实体对象

    1. var polygon = viewer.entities.add({
    2. polygon: {
    3. hierarchy: {
    4. positions: [new Cesium.Cartesian3(290254.5148736448, 5637924.074937166, 2971777.4768239637),
    5. new Cesium.Cartesian3(286432.14053509803, 5640804.651089405, 2966391.9275969476),
    6. new Cesium.Cartesian3(283512.2666752818, 5640502.494127799, 2969385.3689191523),
    7. new Cesium.Cartesian3(287036.36797237827, 5636827.146248645, 2974105.8904601005)
    8. ]
    9. },
    10. material: Cesium.Color.BLUE.withAlpha(0.5),//面颜色
    11. outline: true,//边框是否显示
    12. outlineWidth: 5,//边框线宽度
    13. outlineColor: Cesium.Color.YELLOW,//面边框线颜色
    14. perPositionHeight:true//是否使用每个位置的高度
    15. }
    16. });
    17. viewer.zoomTo(polygon);//定位

    1.2 鼠标左键按下事件

           鼠标左键按下接口为 Cesium.ScreenSpaceEventType.LEFT_DOWN,具体代码如下:

    1. viewer.screenSpaceEventHandler.setInputAction(function(e) {
    2. leftDownAction(e, viewer)
    3. }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

           鼠标左键按下需要获取选中的实体对象,选择(单击选择一个对象)是我们需要与基本API进行短暂交互的领域之一。使用 scene.pick 和 scene.drillpick 检索实体。小编这里采用scene.drillPick。那 scene.drillPick 和 scene.pick 的区别是什么呢?

           如果把 scene.drillPick(click.position) 中 drillPick 改成 pick,那么当鼠标点击或滑过时该位置存在多个 entity,哪怕点线面不在同一高度,面 entity 都可能会盖住点线 entity,从而使得被遮盖的点或线无法响应点击和滑过事件。

    1. let entity = ''
    2. let positions = null // 记录选中实体的位置信息
    3. let newPosition = null // 记录鼠标移动的位置
    4. let diff = [] // 记录选中实体与鼠标位置信息的差异
    5. // 拖拽实体对象-左键按下
    6. function leftDownAction(e, viewer) {
    7. entity = viewer.scene.drillPick(e.position, 1)[0];
    8. var position = changeToThree(e.position, viewer);
    9. if(entity) {
    10. // 锁定相机
    11. if(entity.id.polygon) {
    12. if(!entity.id.polygon.hierarchy._value) {
    13. return ''
    14. }
    15. positions = entity.id.polygon.hierarchy._value.positions;
    16. } else if(entity.id.polyline) {
    17. if(!entity.id.polyline.positions._value)
    18. return
    19. positions = entity.id.polyline.positions._value;
    20. };
    21. // 记录选中实体与鼠标位置信息的差异
    22. positions.forEach(function(item) {
    23. diff.push({
    24. x: item.x - position.x,
    25. y: item.y - position.y,
    26. z: item.z - position.z
    27. })
    28. });
    29. viewer.scene.screenSpaceCameraController.enableRotate = false;
    30. }
    31. }

    定义一个将经纬度格式转为世界坐标格式的方法

    1. // 定义一个将经纬度格式转为世界坐标格式的方法
    2. function changeToThree(position, viewer) {
    3. if(!position) return [];
    4. return viewer.scene.globe.pick(viewer.camera.getPickRay(position), viewer.scene);
    5. }

    1.3 鼠标移动事件

    1. viewer.screenSpaceEventHandler.setInputAction(function(e) {
    2. mouseMoveAction(e, viewer)
    3. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    1. // 拖拽实体对象-鼠标移动
    2. function mouseMoveAction(e, viewer) {
    3. if(entity) {
    4. // 获取移动点的位置,且将格式转为世界坐标
    5. const movePosition = changeToThree(e.endPosition, viewer);
    6. // 根据鼠标位置以及选中实体与鼠标位置信息的差异计算出移动后的实体位置
    7. newPosition = diff.map(item => ({
    8. x: item.x + movePosition.x,
    9. y: item.y + movePosition.y,
    10. z: item.z + movePosition.z
    11. }));
    12. if(entity.id.polygon) {
    13. // 动态改变面的位置信息
    14. entity.id.polygon.hierarchy = new Cesium.CallbackProperty(function() {
    15. return new Cesium.PolygonHierarchy(newPosition)
    16. }, false);
    17. entity.id.polygon.positions = new Cesium.CallbackProperty(function() {
    18. return newPosition
    19. }, false);
    20. } else {
    21. entity.id.polyline.positions = new Cesium.CallbackProperty(function() {
    22. return newPosition
    23. }, false);
    24. };
    25. };
    26. }

    1.4 鼠标左键抬起事件

    1. viewer.screenSpaceEventHandler.setInputAction(function(e) {
    2. leftUpAction(e, viewer)
    3. }, Cesium.ScreenSpaceEventType.LEFT_UP);
    1. // 拖拽实体对象-左键抬起
    2. function leftUpAction(e, viewer) {
    3. if(entity.id.polygon) {
    4. entity.id.polygon.hierarchy = newPosition;
    5. entity.id.polygon.positions = newPosition;
    6. } else {
    7. entity.id.polyline.positions = newPosition;
    8. };
    9. positions = null; // 记录选中实体的位置信息
    10. newPosition = null; // 记录鼠标移动的位置
    11. diff = []; // 记录选中实体与鼠标位置信息的差异
    12. entity = null;
    13. // 解除相机锁定
    14. viewer.scene.screenSpaceCameraController.enableRotate = true;
    15. }

    二、运行效果

    三、注意事项

           构建面实体对象需要用到 perPositionHeight参数,该参数用于指定是否使用每个位置的高度。这里需要设置为 true,否则默认 false 贴地,面边框不会和面一起跟随鼠标移动而移动,会是以下图 3.1 的效果。

    图3.1 面边框不会和面一起跟随鼠标移动而移动

  • 相关阅读:
    Java并发 JUC工具类:CyclicBarrier详解
    让我们拥抱DataV,感受数据可视化的魅力
    JVM知识分享(PPT在资源里)
    网络协议:什么是网络分层的七四五
    查看服务器的配置,系统,cpu等信息
    Java关键字、转义字符与运算符优先级
    详细介绍BERT模型
    2022年Java秋招面试,程序员求职必看的Dubbo面试题
    为何学linux及用处
    伦敦银现货市场如何使用多条均线?
  • 原文地址:https://blog.csdn.net/supermapsupport/article/details/132799526