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

作者:nannan

目录

前言

一、代码思路

[1.1 绘制面实体对象](#1.1 绘制面实体对象)

[1.2 鼠标左键按下事件](#1.2 鼠标左键按下事件)

[1.3 鼠标移动事件](#1.3 鼠标移动事件)

[1.4 鼠标左键抬起事件](#1.4 鼠标左键抬起事件)

二、运行效果

三、注意事项


前言

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

一、代码思路

1.1 绘制面实体对象

cs 复制代码
var polygon = viewer.entities.add({
	polygon: {
		hierarchy: {
			positions: [new Cesium.Cartesian3(290254.5148736448, 5637924.074937166, 2971777.4768239637),
			new Cesium.Cartesian3(286432.14053509803, 5640804.651089405, 2966391.9275969476),
			new Cesium.Cartesian3(283512.2666752818, 5640502.494127799, 2969385.3689191523),
			new Cesium.Cartesian3(287036.36797237827, 5636827.146248645, 2974105.8904601005)
		     ]
	    },
		material: Cesium.Color.BLUE.withAlpha(0.5),//面颜色
		outline: true,//边框是否显示
		outlineWidth: 5,//边框线宽度
		outlineColor: Cesium.Color.YELLOW,//面边框线颜色
		perPositionHeight:true//是否使用每个位置的高度
	}
});
viewer.zoomTo(polygon);//定位

1.2 鼠标左键按下事件

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

javascript 复制代码
viewer.screenSpaceEventHandler.setInputAction(function(e) {
   leftDownAction(e, viewer)
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

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

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

javascript 复制代码
let entity = ''
let positions = null // 记录选中实体的位置信息
let newPosition = null // 记录鼠标移动的位置
let diff = [] // 记录选中实体与鼠标位置信息的差异
// 拖拽实体对象-左键按下
function leftDownAction(e, viewer) {
	entity = viewer.scene.drillPick(e.position, 1)[0];
	var position = changeToThree(e.position, viewer);
	if(entity) {
	    // 锁定相机
		if(entity.id.polygon) {
			if(!entity.id.polygon.hierarchy._value) {
				return ''
			}
			positions = entity.id.polygon.hierarchy._value.positions;
		} else if(entity.id.polyline) {
		if(!entity.id.polyline.positions._value)
			return
			positions = entity.id.polyline.positions._value;
		};
		// 记录选中实体与鼠标位置信息的差异
		positions.forEach(function(item) {
			diff.push({
				x: item.x - position.x,
				y: item.y - position.y,
				z: item.z - position.z
			})
		});
	    viewer.scene.screenSpaceCameraController.enableRotate = false;
	}
}

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

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

1.3 鼠标移动事件

javascript 复制代码
viewer.screenSpaceEventHandler.setInputAction(function(e) {
	mouseMoveAction(e, viewer)
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
javascript 复制代码
// 拖拽实体对象-鼠标移动
function mouseMoveAction(e, viewer) {
	if(entity) {
		// 获取移动点的位置,且将格式转为世界坐标
		const movePosition = changeToThree(e.endPosition, viewer);
		// 根据鼠标位置以及选中实体与鼠标位置信息的差异计算出移动后的实体位置
		newPosition = diff.map(item => ({
			x: item.x + movePosition.x,
			y: item.y + movePosition.y,
			z: item.z + movePosition.z
		}));
		if(entity.id.polygon) {
			// 动态改变面的位置信息
			entity.id.polygon.hierarchy = new Cesium.CallbackProperty(function() {
				return new Cesium.PolygonHierarchy(newPosition)
			}, false);
			entity.id.polygon.positions = new Cesium.CallbackProperty(function() {
				return newPosition
			}, false);
		} else {
			entity.id.polyline.positions = new Cesium.CallbackProperty(function() {
				return newPosition
		       }, false);
		};
	
	};
}

1.4 鼠标左键抬起事件

javascript 复制代码
viewer.screenSpaceEventHandler.setInputAction(function(e) {
	leftUpAction(e, viewer)
}, Cesium.ScreenSpaceEventType.LEFT_UP);
javascript 复制代码
// 拖拽实体对象-左键抬起
function leftUpAction(e, viewer) {
	if(entity.id.polygon) {
		entity.id.polygon.hierarchy = newPosition;
		entity.id.polygon.positions = newPosition;
	} else {
		entity.id.polyline.positions = newPosition;
	};
	positions = null; // 记录选中实体的位置信息
	newPosition = null; // 记录鼠标移动的位置
	diff = []; // 记录选中实体与鼠标位置信息的差异
	entity = null;

	// 解除相机锁定
	viewer.scene.screenSpaceCameraController.enableRotate = true;
}

二、运行效果

三、注意事项

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

相关推荐
supermapsupport15 小时前
SuperMap GIS 基础产品 FAQ 集锦(20260918)
gis·supermap·iserver
supermapsupport1 天前
SuperMap iClient3D for WebGL 交互式栅格信息查询
webgl·supermap
前端小崔5 天前
Three.js 与 Cesium 融合实战问题汇总
前端·three.js·cesium
洛兮银儿5 天前
前端页面引入cesium
前端·cesium
GISBox8 天前
数字孪生项目必备:RVT模型转3DTiles格式的高效解决方案
gis·cesium·格式转换·服务发布·gisbox·rvt切片·3dtiles格式
ToTacview8 天前
Web 可视化卡顿的归因方法论:以“流畅一段、停顿一下“为例的代码级根治
cesium
夜郎king9 天前
基于天地图 Cesium 三维服务实现三维地球及地球自转实践
数据分析·cesium·3d地图·三维地球
luckystar513~11 天前
Navara是WebGIS的第三条路吗?
gis·cesium·mapbox·地图引擎·地理可视化
灵境(虚幻知音)17 天前
WebGL 不支持>1px的线绘制,那 Cesium 的带宽度的线是怎么画出来的?
webgl·cesium·着色器
ToTacview21 天前
WebGL 没有几何着色器,那 Cesium 的粗线是怎么画出来的?
cesium