Offsetting Billboard position to move click area

I have a GeoJSON data source that I’m loading like this:

Cesium.GeoJsonDataSource.load(data, {
stroke: Cesium.Color.fromBytes(0, 230, 240, 40),
markerColor: Cesium.Color.fromHsl(0, 0, 0, 0.01),
}).then(function(dataSource) {
viewer.dataSources.add(dataSource);

``

I have custom markers, so I made the default markers transparent to the user, but not totally transparent because when they are totally transparent, you can’t click on them. The problem is that the click area is above the visible marker. Is there a way to either shift/offset the billboard position to above my custom markers, or make my markers clickable? I haven’t been able to find anything about how to do this in the docs.

For reference, here is my website: https://www.arelplane.com/@arelenglish

Thanks for the help!

Hi Arel,

So are your custom markers implemented in Cesium, or are they all styled GeoJSON? I’m not aware of a way by just styling the GeoJSON in the load function. But if you have created billboards, you should be able to specify both the verticalOrigin and the pixelOffset for them.

Thanks,

Gabby

My custom markers are styled billboards, like this:

function setAirportIcon(entity, top_airport_visit_count) {
billboards.add({
position : entity.position.getValue(viewer.clock.currentTime),
image : airportIcon,
color : new Cesium.Color.fromHsl(0, 0, 1, setOpacity(top_airport_visit_count, entity))
});
}

``

I have lines that represent peoples flights that go to and from each billboard, so I can’t move the custom billboard because it’s over top of a specific geographical feature (usually an airport). What I can’t figure out how to do is get the custom billboard to be clickable, or move the default marker to be placed over the billboard instead of above it. Does that make sense?

Here is a screenshot:

You can see the airport icon, which is my custom billboard, and the cesium default marker. I make the markers transparent so they don’t show up to the user, but can still be clicked on for information about that airport. The problem is that the click area is above the billboard, which is confusing for users who can’t see the marker.

So, either I’m on the totally wrong track here, or my two options are:

  • find a way to make the billboard clickable
  • find a way to move the marker down so it overlaps the billboard.
    Is there a way to actually change the styling of a marker so that using billboards isn’t necessary?

Thanks,

Arel

The answer to making the billboard clickable is pretty straightforward. Just add an entity name to display as the title of the infobox, and/or an entity description for the content of the infobox.

As for styling the GeoJSON marker, when you load in a data source, we represent all the markers will billboards, which you can iterate through and customize like any other entity. See our Cesium Workshop tutorial section on Loading and Styling Entities. (That section also covers using the description property I mentioned above.)

I’m already doing the above things, as seen in the website and screenshots I posted above. The problem is that the entity box only shows up when clicking on the billobards, but doesn’t show up when clicking on the custom markers. As far as I can tell, you can’t change the appearance of the default billboards, but you can create custom markers, and you can hide the default billboard. Is that correct?

I believe you should be able to change the properties of the marker billboard directly, see the examples in the Workshop tutorial.

What properties? I couldn’t see any ability to move the billboard, or change its appearance, besides color and icon changes. I also can’t find any ways to make a custom marker clickable. Thats why I’m asking this question.

In the above snippet you posted, you can add additional code after you load
in the GeoJson data to iterate through the EntityCollection
<https://cesiumjs.org/Cesium/Build/Documentation/EntityCollection.html>
which contains the entities loaded in the scene, then style them (see the
Workshop tutorial linked above for more examples).

Cesium.GeoJsonDataSource.load(data, {
      stroke: Cesium.Color.fromBytes(0, 230, 240, 40),
      markerColor: Cesium.Color.fromHsl(0, 0, 0, 0.01),
    }).then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      // Iterate through and style billboards
      var entities = dataSource.entities.values;
      for (var i = 0; i < entities.length; ++i) {
         var entity = entities[i];
         if (Cesium.defined(entity.billboard)) {
            // Entity styling code here
            entity.billboard.image = '/anotherImage.png';
                  }
             }
    });

The markers are represented as Billboards, so you can set any of the
properties of BillboardGraphics
<https://cesiumjs.org/Cesium/Build/Documentation/BillboardGraphics.html?classFilter=billboardG>,
including *name* and *description*.

Thank you! That helped a lot. I didn't realize you could set the billboard
image directly. I'm running into a familiar problem though, When I set the
image directly, I run into the error drawingBufferWidth must be greater
than zero. Here is an example
<https://cesiumjs.org/Cesium/Apps/Sandcastle/#c=ZVJdb9sgFP0rKC921Aoc53t2o0mdNGmatIdOe5n3gOFis2GIADtKp/73QpxkTccL3HvOuZ8M1KJBwgEsekAaDugRnOw7/OPkSxN2Mh+N9lRqsMm0qPQQNI6BhiAZtfhkBqjSZ/1nMF+c0Z+op0+mtwywMpSnSev93n0gpJHO40b6tq97B5aFBKA9ZqYj1IIC3SjpWgI1ZQKyxZzDfLatF7DORb3M5znk2SbfzIilB5JlC7akWS0WWb4QbD1bimy+3G62sFlBVs/5Kmd8u14RDzEpmN+hsuQe/a30y7TS2LegU9Fr5qXRKQ8lTyOGwjm3x69tOEw5HznFDeXZmO67uUXCnEJT0ktwYVQRwhcbD1T14M5MYSxKI10GXlaEq7wqcRyGbwt0dyevdd2EPwbRhf1T/ir+UaRA6XkhHERYIE9HBa6lUrWhlk9vYsbznoFlR5u46wRjcno7IiiTKrIaKZI3CV/G50ucbDG5n5TOHxXsRu9H2e2N9ai3Kg2hPHR7RcNOSN2zPxCW71wcXUkuopLLAUn+UE3efcNqgpiizgVE9Eo9yWeoJruSBP6NLP45qZtvA1hFj5HSznZfRyfGuCTB/F/ljVE1tW8ivgI>.
When I'm developing locally, I only get that crash when I'm trying to
conditionally set different images for different values, like this:
entity.properties.feature_type._value.

I'm using Chrome version 65.0.3325.181 on OSX 10.13.4.

It sounds like you may be running out of memory with so many billboards. I
was not able to reproduce on my machine.

Take a look at this issue
<https://github.com/AnalyticalGraphicsInc/cesium/issues/6081>, it shows an
example of using a *BillboardCollection* instead of using entities. It will
instance billboard that use the same image (grouping them together to send
to the GPU).

Using a BillboardCollection instead of entities does solve the crashing
problem, but I can't figure out how to make each billboard clickable when
using billboard collections. It brings me back to the original problem of
having the default billboard over top of the custom billboard, and not
being able to click on the custom billboard. See the picture below:

<https://lh3.googleusercontent.com/-c7xjrqFPpvY/Wst-CV7H7XI/AAAAAAAALm0/UO8nL2_6Tf8ZIZ70k1SQl_4lC0B2z_fwgCLcBGAs/s1600/Screen%2BShot%2B2018-04-09%2Bat%2B10.51.17.png>

Oh shoot, I forgot about the initial intention to make them clickable.

Although more complex that using entities, you can implement picking
<https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/index.html?src=Picking.html&label=Showcases>.
This will perform better than using entities, and give you a lot more
flexibility on what happens when you click on a billboard/marker.

Cool. I’ll look into the Picking API. Thanks for the help!