cesium鼠标控制键盘_Cesium开发工具篇 | 02事件应用

无论是前端系统,还是二维/三维GIS应用系统,都离不开各种事件的应用,尤其是鼠标的单击、双击事件。 Cesium 根据事件的类型、用途,将事件应用分成了三大类。一种是以鼠标操作(左键、中键、右键操作等)为主的 ScreenSpaceEventHandler 类,另一种是通用的事件类 Event ,该类通常在容器类内部实例化,并作为某个属性的类型直接被调用,比如 viewer.clock.onTick、viewer.selectedEntityChanged、camera.moveStart、camera.moveEnd、scene.preRender、cesium3DTileset.allTilesLoaded等这些属性都是 Event 类型;最后一种则是相机控制方面的事件类 screenSpaceCameraController,该类通过与CameraEventType类配合实现相机的控制。下面我主要介绍几个比较常用的事件应用。

鼠标事件

鼠标事件可以说是GIS系统里面关于事件应用最常用的一个了,点击地图上的某一个 graphic,并获取其属性信息,就是鼠标事件应用最熟悉的一个场景了。Cesium为实现这一功能,分成了两个过程。首先,传递viewer.canvas参数实例化ScreenSpaceEventHandler类,比如实例化后的名称为handler;其次,为 handler 注册鼠标事件的监听;最后,在监听事件的回调方法中获取 event.position ,并将其作为参数执行scene.pick 方法获取对应的选中对象。

1)ScreenSpaceEventHandler

对 ScreenSpaceEventHandler 类进行实例化,注册事件、注销事件代码如下:

var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

let eventType = Cesium.ScreenSpaceEventType.LEFT_CLICK;

//注册事件

handler.setInputAction((event) => {

console.log(event);

}, eventType);

//注销事件

handler.removeInputAction(eventType);

上面代码中的事件类型 eventType 直接采用了 ScreenSpaceEventType 中的常量,示例中注册鼠标左击事件。根据实际场景需求,eventType 的值可按需赋值,包括以下几种:

2)要素拾取

假如应用场景是点击要素获取其属性信息,这个时候就需要在鼠标左键的注册事件中获取 event 结果,核心代码如下:

var picked = viewer.scene.pick(event.position);

这个时候就可以根据获取到的对象类型进行操作了。

if (Cesium.defined(picked)) {

if (picked.id && picked.id instanceof Cesium.Entity) {

console.log("选中了Entity");

}

if (picked.primitive instanceof Cesium.Primitive) {

console.log("选中了Primitive");

}

if (picked.primitive instanceof Cesium.Model) {

console.log("选中了模型");

}

if (picked instanceof Cesium.Cesium3DTileFeature) {

console.log("选中了3DTile");

}

}

3)Entity选择

Cesium 针对于通过 Entity 方式添加的几何图形,提供了一个非常方便的属性selectedEntityChanged(viewer类事件类型的属性)来帮助我们获取选中的Entity,通过这个属性,用户无需再写注册鼠标事件了。示例代码如下:

viewer.selectedEntityChanged.addEventListener(function (entity) {

console.log(entity.id);

});

在某些场景中,我们可能需要跟踪某一辆车或某一个人员,这是我们可以把车辆或人员Entity赋给viewer.trackedEntity,相机就会自动跟踪你绑定的Entity了。实际场景中,我们并不是始终跟踪某一个车辆,有时需要切换到另一个车辆,当你切换正在跟踪的车辆时,其实我们触发了viewer.trackedEntityChanged事件,这样我们就可以在此事件中实时获取车辆行驶状态了。

viewer.trackedEntityChanged.addEventListener(function (entity) {

console.log(entity.id);

});

相机事件

相机控制事件类 screenSpaceCameraController 并不是像鼠标事件相关类 ScreenSpaceEventHandler 那样需要提前实例化。Cesium在Viewer类的实例化过程中,也实例化了其他很多类,其中就包括ScreenSpaceCameraController类,并把实例化结果赋值给了viewer.scene.screenSpaceCameraController。所以,我们直接去操作viewer.scene.screenSpaceCameraController就可以了。

1)通过鼠标控制

通过鼠标控制相机的方式取决于CameraEventType的常量,包括以下几种:

其中,鼠标的默认操作如下:

下面我们修改默认的鼠标操作,实现中键缩放、右键旋转。核心代码如下:

viewer.scene.screenSpaceCameraController.tiltEventTypes = [

Cesium.CameraEventType.RIGHT_DRAG,

Cesium.CameraEventType.PINCH,

{

eventType: Cesium.CameraEventType.LEFT_DRAG,

modifier: Cesium.KeyboardEventModifier.CTRL,

},

{

eventType: Cesium.CameraEventType.RIGHT_DRAG,

modifier: Cesium.KeyboardEventModifier.CTRL,

},

];

viewer.scene.screenSpaceCameraController.zoomEventTypes = [

Cesium.CameraEventType.MIDDLE_DRAG,

Cesium.CameraEventType.WHEEL,

Cesium.CameraEventType.PINCH,

];

2)通过键盘控制

主要是通过操作键盘实现相机的漫游,比如前进、后退、向上、向下等等,是不是感觉自己在玩穿越火线游戏,响起熟悉的声音:headshot、double kill、multi kill、fire in the hole、......,打住!!!狂点鼠标也不会发射子弹的。好了,我们把感觉拉回来现场,继续学习Cesium。实现键盘漫游主要是通过键盘调用相机的moveForward、moveBackward、moveLeft、moveRight、moveUp、moveDown方法。下面为部分核心代码,查看完整代码请浏览GitHub地址https://github.com/ls870061011/cesium_training/tree/main/examples中的3_2部分。

viewer.clock.onTick.addEventListener(function (clock) {

var camera = viewer.camera;

if (flags.looking) {

var width = canvas.clientWidth;

var height = canvas.clientHeight;

// Coordinate (0.0, 0.0) will be where the mouse was clicked.

var x = (mousePosition.x - startMousePosition.x) / width;

var y = -(mousePosition.y - startMousePosition.y) / height;

var lookFactor = 0.05;

camera.lookRight(x * lookFactor);

camera.lookUp(y * lookFactor);

}

// Change movement speed based on the distance of the camera to the surface of the ellipsoid.

var cameraHeight = ellipsoid.cartesianToCartographic(camera.position)

.height;

var moveRate = cameraHeight / 100.0;

if (flags.moveForward) {

camera.moveForward(moveRate);

}

if (flags.moveBackward) {

camera.moveBackward(moveRate);

}

if (flags.moveUp) {

camera.moveUp(moveRate);

}

if (flags.moveDown) {

camera.moveDown(moveRate);

}

if (flags.moveLeft) {

camera.moveLeft(moveRate);

}

if (flags.moveRight) {

camera.moveRight(moveRate);

}

});

场景渲染事件

场景渲染事件主要包括以下四种:

scene.preUpdate: 更新或呈现场景之前将引发的事件

scene.postUpdate: 场景更新后以及渲染场景之前立即引发的事件

scene.preRender: 场景更新后以及渲染场景之前将引发的事件

scene.postRender: 渲染场景后立即引发的事件

事件的添加和移除代码示例如下:

viewer.scene.preUpdate.addEventListender(callbackFunc);

viewer.scene.preUpdate.removeEventListender(callbackFunc);

比如我们自己写了一个指北针、标签,都可以在scene.preRender监听事件的回调函数中更新指北针状态或者是标签的位置信息。下面的部分核心代码,为场景重新选然后更新自定义标签位置。

viewer.scene.scene-preRender.addEventListener(() => {

if (positions instanceof Array && htmlSize instanceof Array) {

positions.map((ele, index) => {

const html = document.getElementById(`infoTip${index}`);

if (html) {

const canvasPosition = ConversionUtil.degreesToCartesian2(ele.x, ele.y, ele.z);

if (canvasPosition) {

html.style.top = `${canvasPosition.y - htmlSize[index].offsetHeight}px`;

html.style.left = `${canvasPosition.x - htmlSize[index].offsetWidth}px`;

}

}

});

}

)

你可能感兴趣的:(cesium鼠标控制键盘)