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 面边框不会和面一起跟随鼠标移动而移动

相关推荐
汪洪墩35 分钟前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
supermapsupport6 小时前
iClent3D for Cesium 实现无人机巡检飞行效果
gis·cesium·supermap·webgis
不浪brown8 小时前
仅需3行代码!带你做一个3D卫星轨道飞行动画
cesium
白嫖叫上我2 天前
Cesium 无人机航线规划(航点航线)
无人机·cesium
BJ-Giser4 天前
前端解析超图的iserver xml
前端·可视化·cesium
我码玄黄4 天前
在Cesium中加载OD线
前端·javascript·cesium
supermapsupport4 天前
iClient3D for Cesium 实现限高分析
3d·vue·gis·cesium·supermap·webgis
白嫖叫上我5 天前
Cesium 无人机航线规划(区域航线)
无人机·cesium
智方科技9 天前
探索 Cesium 的未来:3D Tiles Next 标准解析
前端·算法·3d·信息可视化·webgl·cesium·tilesbuilder
Allen.l11 天前
Cesium中实现仿ArcGIS三维的动态图层加载方式
javascript·arcgis·cesium