odoe

Label Markers for You ArcGIS JavaScript Apps

Blog Post created by odoe on Jan 7, 2015

esri-labels.png

If you've used the LabelLayer before to annotate your map you are familiar with the fact that you can add labels that match up with your map data. This is a neat feature and I'm sure it's really cool to work with pseudo-annotations in your webmap, but why stop there?

 

Font Awesome for awesomeness

If you've never used Font Awesome, it's a great little CSS Toolkit to add some nice font icons to your web page. This is really useful if you need to build an editor or want to add a little bit of flavor to your site and it's really easy to use. If you've ever added custom fonts to your web page, you know that there's some boilerplate involved. You can get similar icons with Bootstrap and even use them both together.

 

It's also pretty easy to use font icons in Leaflet if you wanted to and I was curious how I could do the same thing with the ArcGIS API for JavaScript. When I first looked at this, there was no LabelLayer in the API yet. I recently had a use-case to use font icons as markers in a project so I dove right in. Turns out, I don't even need the LabelLayer, nor do I care.

 

TextSymbol and Font

So how do we accomplish this? With the introduction of the LabelLayer, there were a couple of other support modules added - Font and TextSymbol. These two modules are the key to awesome markers. There are a few steps you need to do to get this working.

1. The first thing you'll want to do is add a reference to the font awesome css to your page.

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">

2. Define the Font for your TextSymbol.

var font = new Font("20pt", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome");

3. Create a TextSymbol.

var sym = new TextSymbol("", font, treeColor);

What is that weird character I am passing to the TextSymbol? That is the character from Font Awesome I want to use. You'll need to copy and paste the character like any other, but you'll want to use the Font Awesome Cheatsheet for that.

4. Now you can assign the symbol to the graphic and add it to the map.

feature.setSymbol(sym);
map.graphics.add(feature);

 

Here is the full JavaScript for the above snippets.

require([
  "esri/map", 
  "esri/symbols/TextSymbol",
  "esri/tasks/query",
  "esri/tasks/QueryTask",
  "esri/symbols/Font",
  "esri/Color",
  "dojo/domReady!"
], function(
  Map, TextSymbol,
  Query, QueryTask, Font,
  Color
) {
  var map = new Map("map-div", {
    center: [-122.445, 37.752],
    zoom: 14,
    basemap: "gray"
  });

  var treeColor = new Color("#666");
  var treesUrl = "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Street_Trees/FeatureServer/0";
  var font = new Font("20pt", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome");
  // you can use the cheatseeht to copy paste the font symbol
  // http://fortawesome.github.io/Font-Awesome/cheatsheet/
  var sym = new TextSymbol("", font, treeColor);
  var qTask = new QueryTask(treesUrl);
  var query = new Query();
  query.outFields = ["*"];
  //query.where = "TreeID = 0";
  query.where = "1=1";
  query.returnGeometry = true;
  qTask.execute(query).then(function(featureSet) {
    featureSet.features.map(function(feature) {
      feature.setSymbol(sym);
      map.graphics.add(feature);
    });
  });
});

 

Add some flair!

The result of doing the above may get you something like this.

fontmarkers.jpg

That's really cool, but it's not quite right. Groups of trees kind of blend right into each other. My inner-cartographer is wincing. It's ok, we can do something about that. The icons are added via an svg <text> tag, which means we can use CSS to style it.

text {
  text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
}

Now you should get a map that displays the icons like below.

fontmarkers-outline.jpg BAM!

That looks pretty cool if I do say so myself. You find the full demo of this example here.

 

Use it in a renderer

Want to use it as a renderer for a FeatureLayer? No problem.

require([
  "esri/map", 
  "esri/symbols/TextSymbol",
  "esri/symbols/Font",
  "esri/Color",
  "esri/layers/FeatureLayer",
  "esri/renderers/SimpleRenderer",
  "dojo/domReady!"
], function(
  Map, TextSymbol, Font,
  Color, FeatureLayer, SimpleRenderer
) {
  var map = new Map("map-div", {
    center: [-122.445, 37.752],
    zoom: 14,
    basemap: "gray"
  });

  var treeColor = new Color("#666");
  var treesUrl = "http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Street_Trees/FeatureServer/0";
  var font = new Font("20pt", Font.STYLE_NORMAL,
    Font.VARIANT_NORMAL, Font.WEIGHT_BOLD,"FontAwesome");
      // you can use the cheatseeht to copy paste the font symbol
      // http://fortawesome.github.io/Font-Awesome/cheatsheet/
  var sym = new TextSymbol("", font, treeColor);
  var renderer = new SimpleRenderer(sym);
  var fl = new FeatureLayer(treesUrl);
  fl.setRenderer(renderer);
  map.addLayer(fl);
});

 

You'll get the same result as above, but with less code. You can find an example of this here.

 

Why?

Are you asking yourself why bother with this? Why not just use PictureMarkerSymbol and be done with it? I'll tell you why. Fonts scale, pictures don't. Have you ever loaded a PictureMarkerSymbol and had some jagged edges or maybe it was a little blurry? Especially if you tried redefining the size to fit better with your map? Fonts, like SVG vector graphics, scale so that if they are displayed at 8pt or 50pt, they don't pixelate and that is well enough reason for me to use them. This works pretty well and looks good for mobile apps. Granted, the font icon can't be multiple colors or very complicated, but look over the icons alone in Font Awesome or better yet the Mapbox maki icon set and you'll see there is lots of good stuff you may be able to use as a marker on your map.

 

Check out my regular blog for more geodev tips & tricks!

 

Go forth and hack away folks!

Outcomes