Как получить события смены сцены в цезии?

Я хотел бы обнаруживать каждый раз, когда положение камеры, заголовок, шаг или крен меняются в представлении Cesium, чтобы я мог обновлять дисплей, показывающий эти значения. После долгих поисков я в конце концов обнаружил, что могу добавить обработчик событий к совершенно неинтуитивным событиям preRender или postRender в объекте Scene виджета. Однако оба этих события запускаются непрерывно, сотни раз в секунду. Я бы предположил, что они стреляют один раз за такт. Есть ли другое событие, которое я могу зарегистрировать, которое просто сработает после изменения вида карты? Я ищу что-то близкое к событию moveend Leaflet, а preRender и postRender не так.

В противном случае, есть ли способ заставить preRender или postRender срабатывать только тогда, когда что-то действительно изменилось?


person dgvid    schedule 25.03.2015    source источник


Ответы (5)


Я бы рекомендовал одно из следующих решений:

  • установите интервал опроса положения камеры с любой частотой, которая имеет смысл для вашего приложения.

    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
    ...
    
  • Прикрепите триггер события к инициатору изменения. Если мышь, то на мышке. Если клавиатура, прикрепите на keyup.

    Объект CameraEventAggregator имеет член с именем anyButtonDown, который может быть полезен для изменения состояния мыши.

  • Вы также можете использовать функцию FlightCompleteCallback камеры. Это должно срабатывать всякий раз, когда камера перемещается, если вы использовали вспомогательные методы для ее перемещения.

person Mike LP    schedule 26.03.2015

Другим решением, не использующим таймер, является прослушивание событий начала и окончания движения камеры.

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;
person Zac    schedule 02.09.2015
comment
Это не работает, когда пользователь вращает глобус, то есть по инерции, кажется, что это срабатывает только при нажатии кнопки мыши вниз, движении, мыши вверх... - person Adam; 10.09.2015
comment
На их gitHub есть открытая ошибка по этой проблеме. В настоящее время у меня такая же проблема. github.com/AnalyticalGraphicsInc/cesium/issues/2839 Надеюсь, они скоро это исправят. - person Zac; 10.09.2015
comment
@Adam Посмотрите мое редактирование, если вам не нужно вращение по инерции, это работает очень хорошо. - person Zac; 28.09.2015

Используя cesium v1.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)
})
person Christopher DeFreitas    schedule 04.02.2017

В дополнение к ответу https://stackoverflow.com/a/42044819/3092437 вы, вероятно, захотите установить viewer.camera.percentageChanged для некоторых маленькое значение, близкое к 0 (но при 0 значении camera постоянно генерирует change событий). Я использую 0.001, это дает довольно хорошую частоту событий на всех уровнях масштабирования.

person TotalAMD    schedule 12.07.2017

Фактический ответ:

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

});

Есть также morphComplete.

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

person Andrew    schedule 29.07.2020