如何在铯中获取场景变化事件?

How to get scene change events in cesium?

我想每次在 Cesium 视图上检测相机位置、航向、俯仰或滚动变化,以便我可以更新显示这些值的显示。经过大量搜索后,我最终发现我可以将事件处理程序添加到小部件的 Scene 对象上的一点也不直观的 preRenderpostRender 事件。然而,这些事件都连续触发,每秒数百次。我猜他们每个时钟滴答发射一次。有没有我可以注册的另一个事件,它会在地图视图更改后触发?我正在寻找接近 Leaflet 的 moveend 事件的东西,preRenderpostRender 不是吗。

如果做不到这一点,有什么方法可以让 preRenderpostRender 仅在实际发生更改时触发?

我会推荐以下解决方案之一:

  • 设置一个间隔,以对您的应用程序有意义的任何频率轮询相机位置。

    var intervalHandle = setInterval(function() {
      var camera = viewer.scene.camera,
        store = {  position: camera.position.clone(),
                   direction: camera.direction.clone(),
                   up: camera.up.clone(),
                   right: camera.right.clone(),
                   transform: camera.transform.clone(),
                   frustum: camera.frustum.clone()
                };
      //update UI elements
      ...
     }, 1000); // every 1 second whatever is best for your application
    ...
    
  • 在更改的发起者上附加一个事件触发器。如果是鼠标,则在 mouseup 上。如果是键盘,则附加到 keyup。

    CameraEventAggregator 对象有一个名为 "anyButtonDown" 的成员,它对鼠标状态更改很有用。

  • 您也可以使用相机的 FlightCompleteCallback。如果您使用辅助方法移动它,只要相机完成移动就会触发。

另一种不使用计时器的解决方案是监听摄像机移动开始和移动结束事件。

viewer.camera.moveStart.addEventListener(function() { 
     // the camera started to move
});
viewer.camera.moveEnd.addEventListener(function() { 
     // the camera stopped moving
});

这些听起来更像是您正在寻找的活动。

[编辑] : 虽然默认情况下启用惯性旋转和缩放并且看起来很酷,但可以非常轻松地禁用它们。这将使 moveEnd 事件按预期触发。这是禁用惯性的方法。

var viewer = new Cesium.Viewer();

viewer.scene.screenSpaceCameraController.inertiaSpin = 0;
viewer.scene.screenSpaceCameraController.inertiaTranslate = 0;
viewer.scene.screenSpaceCameraController.inertiaZoom = 0;

使用cesium v​​1.30,可以使用这段代码:

viewer.camera.changed.addEventListener(function() {
  var deg = Math.round( Cesium.Math.toDegrees(viewer.camera.heading))
  console.log('Heading:', deg)

  var deg = Math.round( Cesium.Math.toDegrees(viewer.camera.pitch))
  console.log('Pitch:', deg)
})

除了答案 之外,您可能还想将 viewer.camera.percentageChanged 设置为接近 0 的某个小值(但 0camera往往会一直生成 change 事件)。我使用 0.001,它在所有缩放级别都提供了相当不错的事件频率。

实际答案:

viewer.scene.morphStart.addEventListener(function(ignore, previousMode, newMode) {

});

还有morphComplete.

https://www.cesium.com/docs/cesiumjs-ref-doc/Scene.html?classFilter=scene#morphComplete