Zac Zac - 1 month ago 23
Javascript Question

Custom cesium html billboard

I would like to be able to create a div and give it a height, width, and class. Then add the div to a Cesium map as a billboard.

I can create billboards with images and labels and also found this link about how to use an svg, but I am having trouble figuring out how to make the billboard contain dynamically produced html. The project this is in uses class names to apply font icons to divs.

Is there a way to insert the html into a billboard? Or is there another class that would be better suited for this? I am new to Cesium and am open to suggestions.

Answer

Billboards are intended to display rasterized data such as images. If you want to render html to one you must create an canvas element, draw the dom elements to it, then pass that canvas to the billboard as it's image property.

If you actually only need to have an icon/image visible and then display some HTML when the user clicks on it, than you should use Entity API to create your Billboard. You are provided with additional properties such as 'description' when you use the Entity API. The description can be a static HTML string or a Callback Property which can be updated as often as necessary. Descriptions are shown when the user picks the entity, usually via mouse click, but can be done programmatically via the viewer.trackedEntity property.

You can run this in Sandcastle or Codepen

var viewer = new Cesium.Viewer('cesiumContainer');

var canvas = document.createElement('canvas');
canvas.width = 300;
canvas.height = 300;

var svgString = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
       '<foreignObject width="100%" height="100%">' +
       '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px; color: #FF0">' +
         '<em>I</em> like' + 
         '<span style="color:white; text-shadow:0 0 2px blue;">' +
         'Cupcakes</span>' +
       '</div>' +
       '</foreignObject>' +
       '</svg>';

var image = new Image();
image.src = 'data:image/svg+xml;base64,' + window.btoa(svgString);

//Need to wait for image to load before proceeding to draw
image.onload = function() {
  canvas.getContext('2d').drawImage(image, 0, 0);

  viewer.entities.add({
    id: 'Cupcake SVG',
    position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
    billboard: {
      image: canvas
    },
    description: '<p>This is a cupcake that can be modified.</p>'
  });
};