I'm using a CallbackProperty for the `description` field of Entities in a collection because I'd like to display a fairly elaborate HTML form and there's no sense paying the cost of building it for each entity in the collection if the user is only going to click on one or two. Because the form is static for any given entity, I set isCalled=true when constructing the CallbackProperty:
coll.add(Cesium.Entity{
name: myObj.Name,
description: descriptionCallback(myObj),
...
});
function descriptionCallback(entity){
return new Cesium.CallbackProperty(function(time, result){
console.log("Building description form", this, entity);
console.trace();
result = "<form action='./post.js'><dl><dt>Object UUID</dt><dd>" + entity.Id + "</dd>" +
"<dt>Object Value</dt><dd>" + entity.Value + "</dd></dl><input type='submit'/></form>";
return result;
}, true);
}
This works as expected, but the `console.log` statement is called on every clock tick (!!!) while the InfoBox is open. I traced through [the CallbackProperty source](https://github.com/AnalyticalGraphicsInc/cesium/blob/1.33/Source/DataSources/CallbackProperty.js#L75) and it appears that there's no caching of the value when getValue() is called; at no point in that file is the value of isConstant (or _isConstant) checked. I thought maybe the [Property source](https://github.com/AnalyticalGraphicsInc/cesium/blob/1.33/Source/DataSources/Property.js) would check in some superclass method but I don't see it there either.
Am I using this wrong, or is this a bug?
Thanks,
James
Hi James,
Nope, you’re completely right! isConstant is used as a hint that value doesn’t change, but it doesn’t mean that getValue isn’t called each time. Doing that kind of caching at the Cesium level would be much more difficult than having the property itself do the caching.
If you want html to be generated on a click event, you might consider using picking. See here for an example: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Picking.html&label=Showcases
Similar to that code example, you could populate the text description on some mouse input.
Hope that helps,
I appreciate the reference but I'm not sure I want to twiddle with the low-level screen events -- I like the default behavior where clicking on an Entity pops up an Infobox and I don't want to interfere with that. Is there maybe a way to register a callback that fires during the click-to-select process, before the InfoBox is opened? If not, I can certainly cache the results so that multiple calls to my CallbackProperty's function don't result in a significant performance hit.
I am left wondering, though, if the framework itself doesn't use isConstant to determine that caching is appropriate, who is the intended audience for isConstant? If I'm going to cache in a callback I'm writing myself, I already know whether the value is immutable or not.
Thanks,
James
Hi James,
Yes! You should be able to use ScreenSpaceEventHandler to achieve this: http://cesiumjs.org/Cesium/Build/Documentation/ScreenSpaceEventHandler.html
You can disable the default handler (which picks an entity on click and displays the text box) and write your own that first populates your entity description, then does the selection.
Here’s the code that creates the default click behavior: https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Widgets/Viewer/Viewer.js#L742 (you should be able to write a similar function to pickAndSelect).
Here’s a code example that demonstrates how you’d disable default handlers then replace them with custom ones: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Camera%20Tutorial.html&label=Showcases
Let me know if you need more help!