Sunday, March 16th, 2014 at 9:38 am by ba3 — Category: Demo
In Part 2 we looked at an example of how to add simple markers with the Browser version of the BA3 Altus Mapping Engine. These markers used a simple image file to act as the representation of the marker on the screen.
What if you want to present a marker that is more complex? For example, what if you want to create text labels for the markers, or complex wind barbs in a thousand variations of angle and intensity? In these cases, you can actually draw the marker images on the fly. Here is the simplest code that behaves this way - it draws an “X” for each marker, but could just as easily draw anything else:
<!doctype html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>BA3 Altus Mapping Engine custom marker demo</title> </head> <body> <style type="text/css"> div.Altus { width: 100%; height: 900px; display: block; } </style> <!--The map view--> <div class="Altus" id="AltusDiv" /> <script type="text/javascript" src="http://dev.ba3.us/js/altus.js"></script> <script type='text/javascript'> var mapView = new Altus(document.getElementById('AltusDiv')); // initializing the base map if (mapView.addInternetMap != null) { mapView.addInternetMap("baseMap","http://otile1.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"); } // Returns a canvas that can be used for drawing // Used by the addMarkerLabel function function createCanvas(width, height) { var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; return canvas; } // defining a function to receive marker tap events. This must exist in some form or app stalls var onDynamicMarkerTapped = function (mapName, markerName, screenX, screenY, markerX, markerY) { console.log("You tapped (or clicked) dynamic marker " + markerName + " on map " + mapName + " at screen point(" + screenX + "," + screenY + ")" + " at marker point (" + markerX + "," + markerY + ")."); }; ///////////////////////////////////////////////////////////////////////// // Draws a label to a canvas, then adds it as a dynamic marker. // mapName - Name of dynamic map. i.e. "Places" // markerName - Unique name for marker. i.e. "323" // labelText - The text want to use fo the marker. i.e. "Raleigh" // fontName - Name of font to us // fontSize - Point size of font to use // lon, lat - Geographic location // Tips: You can spice up this funciton using different font names, sizes // colors etc. var addMarkerLabel = function (altusMapView, mapName, markerName, labelText, fontName, fontSize, lat, lon) { var canvas = createCanvas(16,16);//document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var width = canvas.width; var height = canvas.height; //Clear context.clearRect(0,0,width,height); //Draw the marker (you can draw anything you like here) context.fillStyle = "rgba(255,0,0,255)"; context.strokeStyle = "rgba(255,0,0,255)"; context.beginPath(); context.moveTo(0,height); context.lineTo(width,0); context.moveTo(0,0); context.lineTo(width,height); context.stroke(); context.strokeRect(0,0,width,height); //Get image data from the context var imgd = context.getImageData(0, 0, width, height); //Compute size var numBytes = width * height * 4; //Allocate memory in mapping engine var ptr= altusMapView.Module._malloc(numBytes); var heapBytes= new Uint8Array(altusMapView.Module.HEAPU8.buffer, ptr, numBytes); //Copy image data into mapping engine memory heapBytes.set(new Uint8Array(imgd.data)); //Add the marker altusMapView.addDynamicMarkerWithImageData(mapName, markerName, lon, lat, //Location width/2, height/2, //Anchor point heapBytes.byteOffset, //Memory location width, height); //Image size //Free the memory we allocated altusMapView.Module._free(heapBytes.byteOffset); }; function pageLoaded() { //Add some marker labels mapView.addDynamicMarkerMap("Places"); var fontName = "Arial"; var fontSize = 12; addMarkerLabel(mapView, "Places", "1", "Austin", fontName, fontSize, 30.266925,-97.741268); addMarkerLabel(mapView, "Places", "2", "Corpus Christi", fontName, fontSize, 26.917172, -97.636356); addMarkerLabel(mapView, "Places", "3", "Los Angeles", fontName, fontSize, 34.048108,-118.251557); addMarkerLabel(mapView, "Places", "4", "Seattle", fontName, fontSize, 47.60107,-122.331498); addMarkerLabel(mapView, "Places", "5", "Tampa", fontName, fontSize, 27.934967,-82.460847); addMarkerLabel(mapView, "Places", "6", "Denver", fontName, fontSize, 39.736762,-104.989579); addMarkerLabel(mapView, "Places", "7", "Chicago", fontName, fontSize, 41.864447,-87.628541); addMarkerLabel(mapView, "Places", "8", "Raleigh", fontName, fontSize, 35.784468,-78.682206); addMarkerLabel(mapView, "Places", "9", "San Francisco", fontName, fontSize, 37.801511,-122.473896); addMarkerLabel(mapView, "Places", "10", "New York", fontName, fontSize, 40.744656,-73.994401); }; function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } addLoadEvent(pageLoaded); </script> </body> </html>
If you run this HTML file, you will see something like this:
In place of the “X”s, you can draw anything you like. Play around with it and you will see the possibilities.
You can even draw text labels for markers. In the above code, swap out the function that draws the markers with this code:
///////////////////////////////////////////////////////////////////////// // Draws a label to a canvas, then adds it as a dynamic marker. // mapName - Name of dynamic map. i.e. "Places" // markerName - Unique name for marker. i.e. "323" // labelText - The text want to use fo the marker. i.e. "Raleigh" // fontName - Name of font to us // fontSize - Point size of font to use // lon, lat - Geographic location // Tips: You can spice up this funciton using different font names, sizes // colors etc. var addMarkerLabel = function (altusMapView, mapName, markerName, labelText, fontName, fontSize, lat, lon) { var canvas = createCanvas(256,256);//document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var width = canvas.width; var height = canvas.height; //Clear context.clearRect(0,0,width,height); //Draw the text var x = width / 2; var y = height / 2; context.font = fontSize+'pt '+fontName; context.textAlign = 'center'; context.fillStyle = "rgba(255,0,0,255)"; context.fillText(labelText, x, y); //Grab only the needed pixels of the canvas for the marker image //To this we need to measure the text (this can be refined a bit more //but I can't figure out an accurate text height) var metrics = context.measureText(labelText); var textWidth = metrics.width; var textHeight = metrics.height; var startX = Math.round(x - textWidth/2)-1; var startY = Math.round(y - fontSize)-1; var imageWidth = Math.round(textWidth)+1; var imageHeight = Math.round(fontSize+fontSize/2)+1; //Get image data from the context var imgd = context.getImageData(startX, startY, imageWidth, imageHeight); //Compute size var numBytes = imageWidth * imageHeight * 4; //Allocate memory in mapping engine var ptr= altusMapView.Module._malloc(numBytes); var heapBytes= new Uint8Array(altusMapView.Module.HEAPU8.buffer, ptr, numBytes); //Copy image data into mapping engine memory heapBytes.set(new Uint8Array(imgd.data)); //Add the marker altusMapView.addDynamicMarkerWithImageData(mapName, markerName, lon, lat, //Location imageWidth/2, imageHeight/2, //Anchor point heapBytes.byteOffset, //Memory location imageWidth, imageHeight); //Image size //Free the memory we allocated altusMapView.Module._free(heapBytes.byteOffset); };
When you run this code, you will see 10 labels over the 10 chosen cities:
Learn More!
If you have questions about Altus products and services, the demonstration code or licensing, please contact us at: [email protected]. Also, any feedback, comments or suggestions that you have are always greatly appreciated.