Possiblity to dynamically and smoothly change the colors of the entities

1. A concise explanation of the problem you’re experiencing.

No possiblity to dynamically and smoothly change the colors of the entities. In the case that I use to illustrate the problem, a series of yellow circles is created, and it is required that the transparency of the circles should gradually change over time. It can be implemented by means of direct access to the material property of the ellipse entities, but this way doesn’t work well since it interferes with the animation of other entities and due to it makes the circles blink. I tried to implement the updates via the CallbackProperty, but I didn’t manage to find a solution. Could you please help to solve the problem?

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

//------------------------------- START VIEWER ---------------------------------

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

navigationHelpButton: false,

animation: false,

timeline: false,

homeButton: false,

scene3DOnly : true

});

//----------------------------- NAVIGATE TO PLACE ------------------------------

var lon = 40, lat = 60;

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(lon, lat, 1000), duration: 1});

//--------------------- MANAGE THE ARRAY OF YELLOW CIRCLES ---------------------

var yellowCircles = {}; // Define the array of yellow circles

// Another yellow circle appears in a random place every 5 seconds.

// The lifetime of each circle is 30 seconds

setInterval(function(){

var yc = new createYellowCircle(); // Create a new circle

yellowCircles[yc.id] = yc; // Copy the circle to the array

}, 5000);

// This procedure inspects all circles 4 times per second

// to change the alphas in their material parameters and to remove expired circles

setInterval(function(){

for(var c in yellowCircles){ // Look through all yellow circles

var c_entity = viewer.entities.getById©; // Get an entity of yellow circle

var now = new Date().getTime() / 1000;

var expiration = (now - yellowCircles[c].created) / yellowCircles[c].lifetime; // Check if the circle lifetime is expired or not

if(expiration < 1){ // If the circle is not expired

var alpha = 1 - expiration; // Calculate new alpha (it should decrease from 1 to 0 over time)

yellowCircles[c].color = Cesium.Color.YELLOW.withAlpha(alpha); // Use alpha to update property color of the yellow circle object

/* The commented below operation allows to update the colors, but this solution doesn’t work well, since

  1. it eventually starts oppressing the animation of other objects,

  2. it makes circles blinking

*/

/*

c_entity.ellipse.material = new Cesium.ColorMaterialProperty(yellowCircles[c].color);

*/

} else{ // If the circle is expired

viewer.entities.remove(c_entity); // Remove entity frome viewer

delete yellowCircles[c]; // Remove the correspondent object instance from the array of yellow circles

}

}

}, 250);

// This is an object constructor that creates a new yellow circle

createYellowCircle = function(){

this.created = new Date().getTime() / 1000; // In seconds

this.lifetime = 30; // In seconds

this.color = Cesium.Color.YELLOW.withAlpha(1); // Start from alpha = 1 (opaque circle)

var longitude = lon + 200 * (Math.random() - 0.5) * 1e-5; // Generate the coordinates randomly

var latitude = lat + 200 * (Math.random() - 0.5) * 1e-5;

this.id = Math.floor(Math.random() * 1e12).toString(); // Generate the unique id of the entity

this.entity = {

id : this.id,

position : Cesium.Cartesian3.fromDegrees(longitude, latitude),

/*

The parameter upadate by means of CallbackProperty works fine for position updates,

but it neither allows to update entire ellipse nor

separately its material property

*/

/*

ellipse : new Cesium.CallbackProperty(function(){

return {

semiMinorAxis : 25,

semiMajorAxis : 25,

material : new Cesium.ColorMaterialProperty(this.color)

};

}, false)

*/

ellipse : {

semiMinorAxis : 25,

semiMajorAxis : 25,

material : new Cesium.ColorMaterialProperty(this.color) // !!! No possibility to dynamically update alpha

}

};

viewer.entities.add(this.entity);

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, 500), duration: 2.5}); // Find the new circle on the map

};

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

Object color updates are commonly used in graphical applications.

4. The Cesium version you’re using, your operating system and browser.

Cesium 1.38, Windows, Chrome

I found the hint at the sandcastle reference https://cesiumjs.org/Cesium/Apps/Sandcastle/?src=Hello%20World.html&label=Showcases&gist=635b076158394095e4a4cfa7b0cb78a6
Br, Oleg

// I eventually found that the code below solves the problem

//------------------------------- START VIEWER ---------------------------------

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var lon = 109.17, lat = 55.2;

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(lon, lat, 1000), duration: 1});

//--------------------- MANAGE THE ARRAY OF YELLOW CIRCLES ---------------------

var yellowCircles = {}; // Define the array of yellow circles

// Another yellow circle appears in a random place every 5 seconds

setInterval(function(){

var circleID = Math.floor(Math.random() * 1e12).toString(); // Generate the unique id of the circle object and its entity

yellowCircles[circleID] = new createYellowCircle(circleID); // Create a new circle

}, 5000);

// The procedure to inspect all circles 4 times per second to change the alphas in their color material parameters and to remove the expired circles

setInterval(function(){

for(var c in yellowCircles){ // Look through all yellow circles

if(yellowCircles[c].isExpired()){

var c_entity = viewer.entities.getById©; // Get the yellow circle entity

viewer.entities.remove(c_entity); // Remove entity from the viewer

delete yellowCircles[c]; // Remove the correspondent object instance from the array of yellow circles

}

}

}, 250);

// An object constructor that creates a new yellow circle

function createYellowCircle(circleID){

var created = new Date().getTime() / 1000; // Time of circle creation, in seconds

var lifetime = 30; // // The lifetime of each circle is 30 seconds

var expired = false;

this.isExpired = function(){

return expired;

}

var color = new Cesium.CallbackProperty(function(){ // Change color transparency dynamically

var now = new Date().getTime() / 1000;

var expiration = (now - created) / lifetime; // Check if the circle lifetime is expired or not

if(expiration < 1) // If the circle is not expired

var alpha = 1 - expiration;

else {

var alpha = 0;

expired = true;

}

return Cesium.Color.YELLOW.withAlpha(alpha);

}, false);

var longitude = lon + 200 * (Math.random() - 0.5) * 1e-5; // Generate the coordinates randomly

var latitude = lat + 200 * (Math.random() - 0.5) * 1e-5;

var entity = {

id : circleID,

position : Cesium.Cartesian3.fromDegrees(longitude, latitude),

ellipse : {

semiMinorAxis : 25,

semiMajorAxis : 25,

material : new Cesium.ColorMaterialProperty(color)

}

};

viewer.entities.add(entity);

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, 750), duration: 2}); // Find the new circle on the map

};

Hi Oleg,

Very neat looking example, I’m glad you were able to figure this out! :grinning:

Just a suggestion- if you wanted this to scale and be more efficient, you could instantiate a list of entities up front. When you want to add another circle, just check to see if an entity is “expired” and just update that value rather than create a whole new entity.

Thanks!

Gabby

Thank you, Gabby!
I’ll follow your suggestion.

Br, Oleg