fcbassongis

Adding a drawing tool to the Basic Viewer Javascript template

Blog Post created by fcbassongis Champion on Feb 20, 2015

The web map templates have certainly give me new perspective on rapid app deployment, especially if you're used to coding from scratch with the Javascript API.  The web map templates have almost everything you need and with some customisation and redeployable code you can minimize your coding time a lot.  One function that I was missing in the Basic Viewer template (Github: https://github.com/Esri/basic-viewer-template) was the ability to create drawings/graphics for annotation on the map.

 

Here are the steps I followed to add such a toolset in my demo app.  (All files referenced are within the template folder)

 

1)  Pick or creat an icon for your draw tool in images/icons_black (or icons_white) folder.  Make sure the icon is named "draw.png" to match the toolbar icon setup.

 

2) Specify a new tool object in config/default.js

"tools": [
        {"name": "legend", "enabled": true},
        {"name": "bookmarks", "enabled": false},
        {"name": "layers", "enabled": true},
        {"name": "basemap", "enabled": true},
        {"name": "overview", "enabled": true},
        {"name": "measure", "enabled": true},
        {"name": "edit", "enabled": true, "toolbar": true}, 
        {"name": "print", "enabled": true, "legend": true, "layouts":true, "format":"jpg"},
        {"name": "details", "enabled": true},
        {"name": "share", "enabled": false},
        {"name": "draw", "enabled": true}  // <<= NEW TOOL OBJECT
    ],

 

3)  Add conditional check for the tool in js/has-config.js

has.add("draw", function (g) {
   var draw = getTool("draw", g.config);
   //overwrite the default with app settings
   if (g.config.hasOwnProperty("tool_draw")) {
      draw = g.config.tool_draw;
   }
   return draw;
});

 

4)  Add tool startup code in js/main.js

var toolList = [];
                for (var i = 0; i < this.config.tools.length; i++) {
                    switch (this.config.tools[i].name) {
                    case "legend":
                        toolList.push(this._addLegend(this.config.tools[i], toolbar, "medium"));
                        break;
                    case "bookmarks":
                        toolList.push(this._addBookmarks(this.config.tools[i], toolbar, "medium"));
                        break;
                    case "layers":
                        toolList.push(this._addLayers(this.config.tools[i], toolbar, "medium"));
                        break;
                    case "basemap":
                        toolList.push(this._addBasemapGallery(this.config.tools[i], toolbar, "large"));
                        break;
                    case "overview":
                        toolList.push(this._addOverviewMap(this.config.tools[i], toolbar, "small"));
                        break;
                    case "measure":
                        toolList.push(this._addMeasure(this.config.tools[i], toolbar, "small"));
                        break;
                    case "edit":
                        toolList.push(this._addEditor(this.config.tools[i], toolbar, "medium"));
                        break;
                    case "print":
                        toolList.push(this._addPrint(this.config.tools[i], toolbar, "small"));
                        break;
                    case "details":
                        toolList.push(this._addDetails(this.config.tools[i], toolbar, "medium"));
                        break;
                    case "share":
                        toolList.push(this._addShare(this.config.tools[i], toolbar, "medium"));
                        break;
                    // NEW TOOL - calls _addDraw startup function lower down in file
                    case "draw":
                        toolList.push(this._addDraw(this.config.tools[i], toolbar, "small"));
                        break;
                    default:
                        break;
                    }
                }

 

     Insert between the other _add* functions

_addDraw: function (tool, toolbar, panelClass) {
   //Add the default map description panel
   var deferred = new Deferred();
   if (has("draw")) {
      // CREATE A DIV FOR THE DRAW BUTTONS
      var drawDiv = toolbar.createTool(tool, "panelDraw");  
      var drawToolbar = domConstruct.create("div", {id: "drawToolbar"}, drawDiv);
      drawtool = new Draw({
         map: this.map,                    
      }, drawToolbar);
      drawtool.map = this.map;
      drawtool.on("draw-end", this._addGraphic);
   
      /* add geometry feature buttons */
      // POINT
      domConstruct.create("button",{
         id: "drawPoint",
         innerHTML:"Point",
         onclick:function(){
            drawtool.activate('point');
         }
      },drawToolbar);
      // POLYLINE
      domConstruct.create("button",{
         id: "drawPolyline",
         innerHTML:"Polyline",
         onclick:function(){
            drawtool.activate('polyline');
         }
      },drawToolbar);
       //POLYGON   
      domConstruct.create("button",{
         id: "drawPolygon",
         innerHTML:"Polygon",
         onclick:function(){
            drawtool.activate('polygon');
         }
      },drawToolbar);
      // CIRLCE   
      domConstruct.create("button",{
        id: "drawCircle",
        innerHTML:"Circle",
        onclick:function(){
          drawtool.activate('circle');
        }
      },drawToolbar);
   
     /* add graphic clear buttons */
     // CREATE A DIV FOR THE CLEAR BUTTONS
     var clearDiv = domConstruct.create("div", {id: "clearToolbar"}, drawDiv);
     // CLEAR LAST DRAWN GRAPHIC
     domConstruct.create("button",{
        id: "clearLast",
        innerHTML:"Undo",
        onclick:function(){
           var g = drawtool.map.graphics.graphics;
           drawtool.map.graphics.remove(g[g.length-1]);
        }
     },clearDiv);
     // REMOVE ALL GRAPHICS   
     domConstruct.create("button",{
        id: "clearAll",
        innerHTML:"Remove All Graphics",
        onclick:function(){
           var prompt = confirm("Are you sure you want to remove all map graphics?");
           if (prompt==true) {
              drawtool.map.graphics.clear();
           }
        }
     },clearDiv);
   
     deferred.resolve(true);
  } else {
     deferred.resolve(false);
  }
  return deferred.promise;
},
// ADD THE GRAPHIC CREATED BY THE SELECTED DRAWING TOOL
_addGraphic:function(evt){
  drawtool.deactivate(); 
  // markerSymbol is used for point and multipoint
  var markerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE, 8, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Colr([255,0,0]), 1), new Color([255,255,0,0.5]));
   
  // lineSymbol used for freehand polyline, polyline and line. 
  var lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255,0,0]), 2);
   
  // fill symbol used for extent, polygon and freehand polygon
  var fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255,0,0]), 2), new Color([255,255,0,0.25]));

  var symbol;
  if ( evt.geometry.type === "point" || evt.geometry.type === "multipoint") {
   symbol = markerSymbol;  
  } else if ( evt.geometry.type === "line" || evt.geometry.type === "polyline") {
   symbol = lineSymbol;
  } else {
   symbol = fillSymbol;
  }
  this.map.graphics.add(new esri.Graphic(evt.geometry, symbol));
}

5)  Add icon tooltip text in js/nls/resources.js

"tooltips":{
        "home": "Default extent",
        "locate": "Find my location",
        "legend": "Legend",
        "bookmarks": "Bookmarks",
        "layers": "Layers",
        "basemap": "Basemap gallery",
        "overview": "Overview map",
        "measure": "Measure",
        "edit": "Edit",
        "time": "Time",
        "print": "Print",
        "details": "Details",
        "share": "Share",
        "draw": "Drawing Tools" // <<= NEW TOOL TOOLTIP TEXT
}

 

6)  Add CSS styling for the panel, divs and buttons in css/styles.css

#pageBody_draw div#drawToolbar,#pageBody_draw div#clearToolbar{
  margin-left:20px;
}
#pageBody_draw button{
  display: inline-block;
  cursor: pointer;
  margin: 10px 5px;
  line-height: 18px;
  padding: 5px;
  font-size: 0.75em;
}

 

And that's it.  Happy drawing!

Outcomes