maxdownunder
maxdownunder

Reputation: 5639

CesiumJS - How can I control viewer time and ticks?

What I'd like to do is control the clock ticks for a non-realtime Cesium application. Imagine there's expensive code running, plus I want to give the viewer time to load the tiles before continuing. So how do I disable automatic ticking, and then call tick() manually when my code is ready for it?

Docs for Cesium.Clock say "The clock will only tick when both Clock#canAnimate and Clock#shouldAnimate are true." but that's not what I'm getting. What I currently see:

viewer.clock.canAnimate = false;
viewer.clock.shouldAnimate = false;
viewer.clock.onTick.addEventListener(function(clock){
    console.log("Tick");
});

The result in the console shows the clock still ticking:

Tick
Tick
Tick
Tick
...

What I'd like to do:

viewer.clock.stopTicking(); // or whatever that command would be...
while (someCondition){
    // run expensive code
    tick(); // issue manual tick
}

Thanks for your help! Max

Upvotes: 4

Views: 5366

Answers (2)

emackey
emackey

Reputation: 12448

It's a bit of a legacy quirk of the Cesium API that the Clock's onTick event fires for every animation frame rendered, regardless of whether the clock advances in time or not.

If you want to take control of Cesium's render loop yourself, you can do that like this:

viewer.useDefaultRenderLoop = false;

function myOwnRenderLoop() {
    viewer.resize();
    viewer.render();
    Cesium.requestAnimationFrame(myOwnRenderLoop);
}

Cesium.requestAnimationFrame(myOwnRenderLoop);

Above, I'm using requestAnimationFrame, so the loop runs as fast as possible. But I could replace that with setTimeout to get a slower loop, emulating poor render performance. Note that interactivity and screen updates would slow down with such a method when longer time intervals are used.

viewer.useDefaultRenderLoop = false;

function myOwnRenderLoop() {
    viewer.resize();
    viewer.render();
    window.setTimeout(myOwnRenderLoop, 500);
}

window.setTimeout(myOwnRenderLoop, 500);

Upvotes: 3

ethorn10
ethorn10

Reputation: 1899

So, your console.log is still printing 'Tick' because the onTick continues to fire, regardless of whether the clock is advancing. All you need to do is toggle both the canAnimate and shouldAnimate, as you suspected. So, your example code would basically be:

viewer.clock.canAnimate = false; 
viewer.clock.shouldAnimate = false;
while (someCondition){
    // run expensive code
    // toggle someCondition so we can exit this
}
// set the animate bools back to true so the clock can advance
viewer.clock.canAnimate = true;
viewer.clock.shouldAnimate = true;

To better see this in action, try this (and maybe set the if conditional to 1000 instead of 100):

viewer.clock.canAnimate = false;
viewer.clock.shouldAnimate = false;
var s = 0;
viewer.clock.onTick.addEventListener(function(clock){
    if (s < 100) {
        console.log(viewer.clock.currentTime);
    } else {
        viewer.clock.canAnimate = true;
        viewer.clock.shouldAnimate = true;        
    }
    s++;
});

You'll see that the console.log is printing the same value for 100 (or 1000) times...this is because the currentTime isn't advancing because of the canAnimate and shouldAnimate. Once those are both toggled back to true, the currentTime will advance.

Upvotes: 2

Related Questions