2

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.

Community
  • 1
  • 1
Zac
  • 2,201
  • 24
  • 48

1 Answers1

4

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>'
  });
};
Mike LP
  • 671
  • 8
  • 13
  • Thanks for the answer, but am having a little trouble following. So are you saying that you can use a second canvas as like a "stage" to render the content, then take the data from the canvas and add it to the billboard? How do you add the content to the billboard? You also mentioned the description, what are you referring to? I checked the documentation for the Billboard class but I didn't see a description field. Is this something that can be added? – Zac Jul 06 '15 at 14:29
  • @Zeb let me know if this edit clarified things for you. – Mike LP Jul 10 '15 at 14:58
  • Oh, very nice. I have not seen svgs used like this. This is great, thanks! While its not ideal to have to do that much to get an html on the map it should work for me. – Zac Jul 14 '15 at 13:05
  • To be fair, having to render html to a billboard is a suboptimal scenario. You could have an absolute positioned div over the Cesium Viewer, it just wouldn't be attached to an entity in the viewer as you move around. – Mike LP Jul 14 '15 at 13:49
  • Yeah, thats what I want to avoid. – Zac Jul 14 '15 at 20:56
  • Both Sandcastle and Codepen links are broken. – Rafael Herscovici May 24 '17 at 11:39