CanvasMap
Getting Started Tutorials 3D Reference

Text

Take a look at this text and you'll see that text is actually very complicated to create. In 3D renderings, text requires a lot of polygons to look 3D and look good.

There are a number of different ways to add text to 3D scenes.

Loading Fonts

To render text, we need to have some fonts. The easiest approach to get started is to use the fonts that are defined in the CMFont.js file and then call CMText to load the fonts. You'll need to add an entry to load the CMFint.js file in your header as follows:

<script src="https://gsp.humboldt.edu/Archive/fonts/2019/CMFonts.js" /script> <!-- file with the URLs for the standard fonts --->

The fonts have to be loaded from the server to the client and this is best done before we create any additional maps so we know the fonts are available. One approach is to create a new OnLoad() function that loads the fonts and provides a callback function to the old OnLoad() function to create our maps. First, rename your "OnLoad()" function to something like "LoadMap()" and create a new OnLoad() function that calls CM3Text to load the fonts and provide a callback to your LoadMap() function.

function OnLoad()
{
	// before using text, we need to load the fonts and then we can initialize the map
	CM3Text.LoadFonts(CMFonts,LoadMap);
}

function LoadMap()
{
	// old OnLoad() code
}

3D Text

You can create 3D extruded text for your renderings just like you've seen in the movies. Remember that this is expensive.

In CanvasMap, text can be added using a special layer for general 3D items. The code below will add the text "Antarica" to a geographic map with a very small bevel to make it look good. The extrusion settings are the same as for CM3LayerVector. The Font settings are different from 2D fonts and may change in the future. For now:

Remember that you'll need to change the "SetSetting("PositionOffset",[X,Y,Z])" values based on the spatial reference and units you are using. You can also change the size of the text and change the font size. By default, text is drawn on the x-y plane. You can change this by rotating the text about the x-axis.

// add the layer for the text items
var TheLayerItems=new CM3LayerItems(); 
TheLayerItems.SetSetting("Name","3D Items");
TheMainContainer.AddLayer(TheLayerItems);

// add the text item
var TheText=new CM3Text("Antartica");
TheText.SetSetting("Style","fillStyle","rgba(200,200,200,1)");
TheText.SetSetting("Extrusion","bevelSize",.1);
TheText.SetSetting("Extrusion","bevelThickness",.1);
TheText.SetSetting("Font","size","12");
TheText.SetSetting("Font","GlobalFontIndex",2);
TheText.SetSetting("Item","Rotation",[Math.PI/2,0,0]);
TheText.SetSetting("Item","PositionOffset",[60,-80,10]);
TheLayerItems.AddChild(TheText);

Sprite Text

Another approach is to use a Canvas element to place a "sprite" in the 3D scene. Sprites are special 3D objects that always render toward the view and can be used to put labels that hover over spatial data.

The samle below will add the text "USA" over the US. Note that since sprite text is a Canvas,you can use the same settings for the CM3SpriteText object as you would for other 2D objects.

var TheLayerItems=new CM3LayerItems();
TheLayerItems.SetSetting("Name","3D Items");

var TheBox=new CM3SpriteText("USA");
TheBox.SetSetting("Style","fillStyle","rgba(0,200,255,1)");
TheBox.SetSetting("Text","font","40px Arial");
TheBox.SetSetting("Position","Translations",[-90,40,10]);
TheLayerItems.AddChild(TheBox);

TheMainContainer.AddLayer(TheLayerItems);

The code sample below shows a full example of pulling text from a vector layer's attributes and displaying it in sprite text objects in a scene with projected data.

var TheLayerItems=new CM3LayerItems(); // create the layer for the items
TheLayerItems.SetSetting("Name","3D Items"); // set the name so we can see it in the layer list
TheMainContainer.AddLayer(TheLayerItems); // add the layer to the scene

// save the item layer into the point layer so we can access it after the point layer loads
TheLayer.TheLayerItems=TheLayerItems; 

// save the OnLoad function call before we replace it
TheLayer.CMLayerVector3D_OnLoad=TheLayer.OnLoad;

// replace the onload call with our own to add the labels
TheLayer.OnLoad=function()
{
	// call the old onload function
	this.CMLayerVector3D_OnLoad();
	
	var TheDataset=this.GetDataset(); // get the dataset that contains the data
	
	var CallSignIndex=TheDataset.GetAttributeIndexFromHeading("CALL_SIGN");
	
	var NumFeatures=TheDataset.GetNumFeatures();
	
	var TheRegions=TheDataset.GetRegions(); // get the spatial data for the features
	
	var TheLayerItems=this.TheLayerItems; // get back our layer for the labels
	
	for (var i=0;i<NumFeatures;i++)
	{
		var TheRegion=TheRegions[i]; // get the region (features spatial data)
		
		var TheArea=TheRegion[0]; // get the area within the region
		
		var ThePoly=TheArea[0]; // get the poly within the area
		
		var X=ThePoly[0][0]; // get the x and y values
		var Y=ThePoly[1][0];
		var Z=15000; // set the Z value to be above the surface
		
		// get the attribute to put into the text box
		var TheCallSign=TheDataset.GetAttributeCell(CallSignIndex,i);
		
		// create the object for the text
		var TheBox=new CM3SpriteText(TheCallSign);
		
		// set the settings for drawing the text and box
		TheBox.SetSetting("Style","fillStyle","rgba(0,200,255,1)");
		TheBox.SetSetting("Text","font","20px Arial");
		
		TheBox.SetSetting("Position","Translations",[X,Y,Z]); // set the position of the center of the box
		TheBox.SetSetting("Position","Scales",[20000,20000,1]); // ake the box larger for projected data
		
		TheLayerItems.AddChild(TheBox); // add the box to the layer
	}
}