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

相关推荐
探索前端9 小时前
3dtiles加载时被地形遮挡问题研究及处理思路
前端·3d·cesium
supermapsupport7 天前
SuperMap GIS 基础产品 FAQ 集锦(20260807)
webgl·supermap·idesktopx
兔年鸿运Q小Q10 天前
cesium1.140以上版本加载地形
arcgis·cesium
用户831348593069811 天前
Vue3+Cesium实现阴天乌云+下雨天气特效
vue.js·webgl·cesium
REDcker21 天前
Cesium三维WebGIS入门详解
前端·gis·web·cesium·webgis
用户831348593069822 天前
Cesium 实现行政区内部遮罩
vue.js·webgl·cesium
探索前端22 天前
Cesium图层加载及影像服务添加
前端·cesium
用户831348593069825 天前
Cesium 实现行政区反向遮罩镂空效果(自定义暗色蒙层+矢量/影像底图切换)
vue.js·webgl·cesium
全栈项目管理程序猿1 个月前
Cesium 实战 11 - 调整饱和度、对比度等参数,加载渲染美化影像底图
cesium
雨中的小蜗牛1 个月前
Cesium实现模型拆解-从底层拓展强行让它和Threejs一样拆解模型
cesium