Highlight Hovered Data Source Entity

All,

I’m loading a geojson of US counties. I’d like a county to be highlighted when the mouse hovers over it. Below is the code I’ve got so far.

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

var scene = viewer.scene;

var handler;

viewer.dataSources.add(Cesium.GeoJsonDataSource.load(’…/Apps/SampleData/us-counties.geojson’));

//Get the array of entities

var color = Cesium.Color.WHITE;

handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);

handler.setInputAction(function(movement) {

var pickedObject = scene.pick(movement.endPosition);

if (Cesium.defined(pickedObject)) {

pickedObject.id.polygon.material.color = color;

}

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

I would think that code would work, but for some reason when I hover over any county it colors all of them white. I’d greatly appreciate any help to explain to me what I’m missing.

-Thanks, Stephen

Okay, I got it to work, but I don’t understand why my solution worked. If I load the data source as a promise, and then in the promise success function loop through the entities and assign them all a color, it works. I don’t understand why that makes a difference though. Any help is appreciated.

-Thanks, Stephen

The problem is that the GeoJSON data is sharing one material for performance/memory reasons. Instead of setting the color property directly, change the entire material.

So

pickedObject.id.polygon.material.color = color;

Becomes

pickedObject.id.polygon.material = color;

And it works as expected.

Got it. Thanks for the explanation. I’m also noticing that changing the color of one of these counties on hover is extremely slow. It’s even very slow with the US States topojson file that comes with Cesium. Would anyone have any idea why that is? It doesn’t seem like it should be all that computationally complex. Is there a better way of doing this?

-Thanks, Stephen

This is an area of the Entity API that definitely needs some work. Basically, I want the ability to add “highlight” styles so that you can simply tell us what it should look like when selected/moused over instead of having to manually do stuff yourself. For now, the optimal way to do this is to use CallbackProperty. Here’s a full implementation of what you want to do that should be much more performant.

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

var highlightedEntity;

var highlightColor = Cesium.Color.GREEN.withAlpha(0.6);

var normalColor = Cesium.Color.YELLOW.withAlpha(0.6);

//A property that returns a highlight color if the entity is currently moused over, or a default color otherwise.

function createCallback(entity){

var colorProperty = new Cesium.CallbackProperty(function(time, result){

if(highlightedEntity === entity){

return Cesium.Color.clone(highlightColor, result);

}

return Cesium.Color.clone(normalColor, result);

}, false);

return new Cesium.ColorMaterialProperty(colorProperty);

}

var promise = Cesium.GeoJsonDataSource.load(’…/…/SampleData/ne_10m_us_states.topojson’);

promise.then(function(dataSource) {

viewer.dataSources.add(dataSource);

//Get the array of entities

var entities = dataSource.entities.values;

for (var i = 0; i < entities.length; i++) {

var entity = entities[i];

entity.polygon.material = createCallback(entity);

}

}).otherwise(function(error){

//Display any errrors encountered while loading.

window.alert(error);

});

var scene = viewer.scene;

var handler = viewer.screenSpaceEventHandler;

handler.setInputAction(function(movement) {

var pickedObject = scene.pick(movement.endPosition);

if (Cesium.defined(pickedObject) && pickedObject.id instanceof Cesium.Entity) {

highlightedEntity = pickedObject.id;

} else{

highlightedEntity = undefined;

}

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);