ArcGIS Server Link for Google Maps API: Examples

Concepts | Class References

Table of Contents

Map Types/Overlays:
Services:

Include Scripts

The first step is to include arcgislink.js or arcgislink_packed.js in your document header, after the Google Maps API has loaded. You can use the hosted release version if you do not want to download the script.

<script src="/path/to/extargis_packed.js" type="text/javascript"></script>

Simple Add Map

In the simplest form, you can add an ArcGIS map with the add-on method GMap2.addArcGISMap(url) to the core GMap2 class. You can optionally use a callback function to do extra things with the result.

function init(){
  var map = new GMap2(document.getElementById("map"));
  map.setCenter(new GLatLng(45.5, -122.7), 14);
  var base = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services';
  var tiled = base + '/Portland/Portland_ESRI_LandBase_AGO/MapServer';
  var dyna = base + '/Demographics/ESRI_Census_USA/MapServer';
  map.addArcGISMap(tiled);
  map.addArcGISMap(dyna);
}

View example | Packed | Back to top

Add as ArcGISMapOverlay

ArcGIS Server provides map services to generate map images on the fly, also known as "dynamic map". Dynamic services are implemented as ArcGISMapOverlay, a subclass of GOverlay, and hence can be added with map.addOverlay(). This class is similar to the GGoundOverlay in the core API, as it essentially draws a single image over the map. Any map service can be added as an ArcGISMapOverlay, regardless of whether it's tiled or not.

function init(){
  var map = new GMap2(document.getElementById("map"));
  map.setCenter(new GLatLng(40, -100), 4);
  var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer';
  map.addOverlay(new ArcGISMapOverlay(url));
}

View example | Packed | Back to top

Add mercator tiles as ArcGISMapType

If a map service is pre-rendered as tiles, the application will have a better response time if added as ArcGISTileLayer. If the map service is tiled using the same tiling scheme as Google Maps (WebMercator in ArcGIS), it can be added as a map type directly. The following example constructs a new GMap2 with only an ArcGIS map type and no Google map types.

function init(){
  var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/ESRI_LandBase_WebMercator/MapServer';
  var agsType = new ArcGISMapType(url);
  var map = new GMap2(document.getElementById("map"),{mapTypes:[agsType]});
  map.setCenter(new GLatLng(45.5, -122.7), 15);
}          

View example | Packed | Back to top

Load map tiles on load event

If the map service is not cached using the same tiling scheme as Google maps, then it can not be loaded directly because the system does not know how to request the tiles. It must instead be added asynchronously, after it's received information about the scheme. The following example adds a map service created in ArcGIS online scheme after the "load" event:

function init(){
  var map = new GMap2(document.getElementById("map"));
  map.setCenter(new GLatLng(45.5, -122.7), 15);
  var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/Portland_ESRI_LandBase_AGO/MapServer';
  var agsType = new ArcGISMapType(url);
  GEvent.addListener(agsType,'load', function(){
    map.addMapType(agsType);
    map.setMapType(agsType);
  });
}

View example | Packed | Back to top

Load map tiles without load event

If you do not want to wait until the 'load' event, and you already know how the tiles are built, you can pass an ArcGISProjection to the constructor of ArcGISTileLayer. Note, you still must make sure the ArcGISSpatialReference is in the system already. This is a useful technique when you have many tiled maps a nd they are all using the same tile scheme.

var tileInfo = {
  "rows": 512,
  "cols": 512,
  "dpi": 96,
  "origin": {
     "x": -180,
     "y": 90
   },
  "spatialReference": {
     "wkid": 4326
  },
  "lods": [
     {"level" : 0, "resolution" : 0.351562499999999, "scale" : 147748799.285417}, 
     {"level" : 1, "resolution" : 0.17578125, "scale" : 73874399.6427087}, 
     {"level" : 2, "resolution" : 0.0878906250000001, "scale" : 36937199.8213544}, 
     {"level" : 3, "resolution" : 0.0439453125, "scale" : 18468599.9106772}, 
     {"level" : 4, "resolution" : 0.02197265625, "scale" : 9234299.95533859}, 
     {"level" : 5, "resolution" : 0.010986328125, "scale" : 4617149.97766929}, 
     {"level" : 6, "resolution" : 0.0054931640625, "scale" : 2308574.98883465}, 
     {"level" : 7, "resolution" : 0.00274658203124999, "scale" : 1154287.49441732}, 
     {"level" : 8, "resolution" : 0.001373291015625, "scale" : 577143.747208662}, 
     {"level" : 9, "resolution" : 0.0006866455078125, "scale" : 288571.873604331}, 
     {"level" : 10, "resolution" : 0.000343322753906249, "scale" : 144285.936802165}, 
     {"level" : 11, "resolution" : 0.000171661376953125, "scale" : 72142.9684010827}, 
     {"level" : 12, "resolution" : 8.58306884765626E-05, "scale" : 36071.4842005414}, 
     {"level" : 13, "resolution" : 4.29153442382813E-05, "scale" : 18035.7421002707}, 
     {"level" : 14, "resolution" : 2.14576721191406E-05, "scale" : 9017.87105013534}, 
     {"level" : 15, "resolution" : 1.07288360595703E-05, "scale" : 4508.93552506767}
  ]};
var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/Portland_ESRI_LandBase_AGO/MapServer';
var agsType = new ArcGISMapType(url,{projection: new ArcGISProjection(tileInfo)});
// note no load event listener.
var map = new GMap2(document.getElementById("map"), { mapTypes: [agsType]});
map.setCenter(new GLatLng(45.5, -122.7), 15);

View example | Packed | Back to top

Add as GTileLayerOverlay

Tile layers can also be added as ArcGISTileLayerOverlay, a subclass of GTileLayerOverlay in the core API. If the tile is created with "WebMercator", it can be added on top of the default Google map types. If it is not in "WebMercator", it can only be added as an ArcGISTileLayerOverlay on top of map types with the same tiling scheme. In this case, it's best to initialize the map with only the ArcGIS map types.

var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/ESRI_LandBase_WebMercator/MapServer';
var tileoverlay = new ArcGISTileLayerOverlay(new ArcGISTileLayer(url,{opacity:0.4}));
map.addOverlay(tileoverlay);

View example (Mercator) | Packed (Mercator) | View example (Load) | Packed (Load) | Back to top

Combining Tiled and Dynamic Layer

In many situations, it's ideal to combined a tiled map as a background, with a dynamic layer on top of it. The following example loads the default Google map types (Normal, Satellite, Hybrid), then a tiled map service built on WGS84(4326) with 521x512 pixel tile size, then a tiled map service built on Web-Mercator(102113) with 256x256 pixel tile size, and finally, a dynamic map service whose own spatial reference system is NAD83 GCS(4269) on top of all. As map type changes, the dynamic map will refresh itself to match the underlying spatial reference.

function init(){
  // first init a normal map
  var map = new GMap2(document.getElementById("map"));
  map.setCenter(new GLatLng(45.5, -122.7), 15);

  // now add ArcGIS maps
  var baseUrl = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services';
  var wgs84Url = baseUrl + '/Portland/Portland_ESRI_LandBase_AGO/MapServer';
  var webMercatorUrl = baseUrl + '/Portland/ESRI_LandBase_WebMercator/MapServer';
  var dynaUrl = baseUrl + '/Demographics/ESRI_Census_USA/MapServer';
         
  var wgs84 = new ArcGISMapType(wgs84Url);
  GEvent.addListener(wgs84,'load',function(){map.addMapType(wgs84);});
  var webMercator = new ArcGISMapType(webMercatorUrl);
  GEvent.addListener(webMercator,'load',function(){ map.addMapType(webMercator); });
         
  var dynaOverlay = new ArcGISMapOverlay(dynaUrl);
  map.addOverlay(dynaOverlay);
}   

View example | Packed | Back to top

ArcGISOnline Services

ArcGISOnline is an online geo-spatial service provided by ESRI, Inc. All the tiled map services are based on WGS84 Spatial Reference System with tile size of 512x512.

Check Licensing before you use these services.

The following example creates and loads one ArcGIS base map type, sets that as the maptype for the map, then adds additional services using the GMap2.addArcGISMap(url)

function init(){
  var base = 'http://server.arcgisonline.com/ArcGIS/rest/services';
  var type = new ArcGISMapType(base + '/ESRI_StreetMap_World_2D/MapServer');
  GEvent.addListener(type,'load', function(){
    var map = new GMap2(document.getElementById("map"), {mapTypes: [type]});
    map.setCenter(new GLatLng(40,-95), 4);
    // now add more services
    map.addArcGISMap(base + "/ESRI_Imagery_World_2D/MapServer");
    map.addArcGISMap(base + "/ESRI_ShadedRelief_World_2D/MapServer");
    map.addArcGISMap(base + "/I3_Imagery_Prime_World_2D/MapServer");
    map.addArcGISMap(base + "/NGS_Topo_US_2D/MapServer");
    map.addArcGISMap(base + "/NPS_Physical_World_2D/MapServer");
    map.addArcGISMap(base + "/Demographics/ESRI_00-08PopGrwth_US_2D/MapServer");
    map.addArcGISMap(base + "/Demographics/ESRI_Diversity_US_2D/MapServer");
    map.addArcGISMap(base + "/Demographics/ESRI_MedianIncome_US_2D/MapServer");
    map.addArcGISMap(base + "/Specialty/EVC_Topo_World_2D/MapServer");
  });
}

View example | Packed | Back to top

Enable Map Click

ArcGIS Map Services contains a backend geospatial database that can answer spatial queries about geographic features located at a certain location. The simplest way to use this feature is by calling the add-on method GMap2.enableArcGISClick(). That will cause an infowindow to pop up after the user clicks the map.

function init(){
  var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Portland/Portland_ESRI_LandBase_AGO/MapServer';
  var agsType = new ArcGISMapType([new ArcGISTileLayer(url)]);
  GEvent.addListener(agsType,'load', function(){
    var map = new GMap2(document.getElementById("map"), {mapTypes: [agsType]});
    map.setCenter(new GLatLng(45.5, -122.7), 15);
    // simply enable MapClick 
    map.enableArcGISClick();
    //...
  });
}

View example | Packed | Back to top

Generic ArcGIS Viewer

The library supports virtually all types of ArcGIS Server map service, with rare exceptions:

  1. The map tile is not square (not supported by the Google Maps API API).
  2. The map service is not geo-referenced.
You can build an "ultimate" ArcGIS server mashup using ANY map service:

function addMap(url){
  map.addArcGISMap(url, function(o){
    if (o instanceof ArcGISMapType) {
      map.setMapType(o);
      map.setBounds(o.getTileLayers()[0].getInitialBounds());
    } else if (o instanceof ArcGISMapOverlay) {
      map.setBounds(o.getInitialBounds());
      o.setOpacity(document.getElementById("opacity").value);
      map.zoomIn();
    }
    updateTOC();
  });
}

View example | Packed | Back to top

Use Namespace

Using namespaced libraries can avoid potential class conflicts. The Google AJAX API loader originally introduced the namespace "google.maps" and since v2.86 you can also use that namespace with the normal loader. This library can be used in the namespace "google.maputils.arcgis". To use any of the classes from the library with that namespace, the basic rule is to replace the "ArcGIS" prefix with the namespace.

// first init a normal map
var map = new google.maps.Map2(document.getElementById("map"));
map.setCenter(new google.maps.LatLng(45.5, -122.7), 15);
map.addControl(new google.maps.MapTypeControl());
map.addControl(new google.maps.LargeMapControl());
map.addControl(new google.maps.ScaleControl());
var wgs84Url = baseUrl + '/Portland/Portland_ESRI_LandBase_AGO/MapServer';
var wgs84 = new google.maputils.arcgis.MapType(wgs84Url);
google.maps.Event.addListener(wgs84,'load',function(s){
  map.addMapType(wgs84);
});
var dynaOverlay = new google.maputils.arcgis.MapOverlay(dynaUrl);
map.addOverlay(dynaOverlay);

View example | Packed | Back to top

State Plane Coordinate System

Virtually all GIS data collected by State or Local Governments in Unite States are stored in one of the State Plane Coordinate Systems. In real-world operations, map services (both tiled and dynamic) are published using the native coordinate system the data uses.

When adding an ArcGISTileLayer from a tiled map service, the spatial reference of the map service must be loaded into the internal SpatialReferences collections before it can be used. The library has 3 built-in spatial references: NAD GCS (4269), WGS84 (4326) and "Web Mercator" (102113). It also supports any spatial references based on Lambert Conformal Conic Projection or Transverse Mercator Projection. They can be added either with one line of code by its Well_known_text format or constructed directly with correct parameters. Please use the WKT value from ESRI documentation. Spatial references based on other projections can be used by implementing the ArcGISSpatialReference interface

ArcGISSpatialReferences.addSpatialReference(2264, 'PROJCS["NAD_1983_StatePlane_....UNIT["Foot_US",0.3048006096012192]]');
function init(){
  var url = 'http://maps.ci.charlotte.nc.us/ArcGIS/rest/services/GET/BaseMap/MapServer';
  var agsLayer = new ArcGISTileLayer(url);
  var agsType = new ArcGISMapType([agsLayer]);
  GEvent.addListener(agsType, 'load', function(){
    var map = new GMap2(document.getElementById("map"), { mapTypes: [agsType]});
    //this is a add-on method to use in place of GMap2.setCenter() without knowning the actual latlng;
    map.setBounds(agsLayer.getInitialBounds());
  });
}

View example | Packed | Back to top

Rotating Hosts for Tiles

Some browsers has default limitations on how many concurrent connections can be made to a give host based on URL name, so that when many tiles are being downloaded, some of them have to wait in the queue. One workaround for this issue is to create multiple DNS names with numbers as suffix. There is an option in the ArcGISTileLayer constructor to allow you to specify an 'host pattern', for example, "mt[4].google.com" means to rotate hosts across mt0.google.com, mt1.google.com, mt2.google.com, mt3.google.com (4 hosts)

function init(){
  var url = 'http://maps.ci.charlotte.nc.us/ArcGIS/rest/services/GET/BaseMap/MapServer';
  var agsLayer = new ArcGISTileLayer(url, {
    hosts: "mt[4].ci.charlotte.nc.us"
  });
  var agsType = new ArcGISMapType([agsLayer]);
  GEvent.addListener(agsType, 'load', function(){
    var map = new GMap2(document.getElementById("map"), {
    mapTypes: [agsType]
  });
}

View example | Packed | Back to top

Flat Spatial Reference

This library also include a simple class FlatSpatialReference. Strictly speaking, this is not a true spatial reference, but can be used as a workaround without implementing a real projection class. This class assumes latitude and longitude values are increased evenly. The following example works as if the spatial reference 4326 is not added as an instance of LambertConformalConic. You can add tiled maps service without actually doing anything with ArcGISSpatialReference.

var url = 'http://.../MapServer';
var agsLayer = new ArcGISTileLayer(url);
var agsType = new ArcGISMapType([agsLayer]);
GEvent.addListener(agsType, 'load', function(){
  var map = new GMap2(document.getElementById("map"), {
    mapTypes: [agsType]
  });
  map.setBounds(agsLayer.getInitialBounds());
});

View example | Packed | Back to top

Layer Definition

You can draw a subset of a feature layer inside a dynamic map service (ArcGISMapOverlay) by setting a SQL expression as its definition property. You will have to use the ArcGISLayer class in the REST part of the libarary.

var service = dynaLayer.getMapService();
service.getLayer("Coarse Counties").definition="STATE_NAME='Kansas' and POP2007 > 25000";
service.getLayer("Detailed Counties").definition="STATE_NAME='Kansas' and POP2007 > 25000";
service.getLayer("states").definition="STATE_NAME='Kansas'";

View example | Packed | Back to top

Layer Visibility (TOC)

You can control visibility of a layer inside a dynamic map service (ArcGISMapOverlay) by setting its visible property. There are some limitations on the scale threshold on layers in the REST API. You will have to load the layer resource individually if you want to do a TOC that handles scales.

var service = dynaLayer.getMapService();
service.getLayer("states").visible = true;
dynaLayer.refresh();

View example | Packed | Back to top

Show/Hide HourGlass with events

A dynamic map image may take some time to render. When a intensive server request like map rendering is running in the background, it's helpful to let the user know about it. You can display some sort of hourglass animation image or simply a message such as "loading...". You can accomplish this by handling different "***start" and "***end" events, or use ArcGISUtil#jsonpstart and ArcGISUtil#jsonpend event to monitor all server requests

GEvent.addListener(dynaLayer, 'drawstart', function(){
  document.getElementById('drawing').style.visibility = 'visible';
});
GEvent.addListener(dynaLayer, 'drawend', function(){
  document.getElementById('drawing').style.visibility = 'hidden';
});
GEvent.addListener(ArcGISUtil, 'jsonpstart', function(){
  document.getElementById('working').innerHTML = "working....";
});
GEvent.addListener(ArcGISUtil, 'jsonpend', function(){
  document.getElementById('working').innerHTML = '';
});

View example | Packed | Back to top

Layer Query

You can query a layer with a SQL statement and spatial filters. The result can be displayed as overlays, like markers or polys. You can also attach mouse events to those overlays to make the application more interactive.

function initFunctionality(){
  var layer = dyna.getMapService().getLayer(3);
  var params = {
    returnGeometry: true,
    where: "STATE_NAME = 'South Carolina'",
    outFields: ["NAME", "POP2000", "POP2007", "POP00_SQMI", "POP07_SQMI"],
    outSR: 4326
  };
  layer.query(params, processResultSet);
}

function processResultSet(rs){
  var fs = rs.features;
  for (var i = 0, c = fs.length; i < c; i++) {
    var ovs = createGPolys(fs[i], rs.spatialReference);
    for (var j = 0; j < ovs.length; j++) {
      gmap.addOverlay(ovs[j]);
    }
  }
}

function createGPolys(feat, sr){
  var ovs = ArcGISUtil.fromFeatureToOverlays(feat,sr, style);
  var ov = ovs[j];
  GEvent.addListener(ov, 'mouseover', function(){
    for (var i = 0, ic = ovs.length; i < ic; i++) {
      ovs[i].setStrokeStyle({color: hStyle.outlineColor,weight: hStyle.outlineWeight});
      ovs[i].setFillStyle({ color: hStyle.fillColor,opacity: hStyle.fillOpacity});
    }
    var latlng = ov.getBounds().getCenter();
    gmap.openInfoWindowHtml(latlng, html);
  }); 
  return ovs;
}

View example | Packed | Back to top

Find

Find is an operation supported by a map service to query features based on a single String. It will search the attribute columns of the map layers inside the map service and return matching features.

var params = {
  returnGeometry: true,
  searchText: q,
  contains:!exact,
  layers:['Cities','Rivers','States'],
  searchFields:["CITY_NAME","NAME","SYSTEM","STATE_ABBR","STATE_NAME"],
  sr: 4326
};
service.find(params, processFindResults);
            
function processFindResults(rs) {
  var fs = rs.results;
  for (var i = 0, c = fs.length; i < c; i++) {
    processFindResult(fs[i]);
  }
}
          
function processFindResult(res) {
  var ovs = ArcGISUtil.fromFeatureToOverlays(res);
  gmap.addOverlays(ovs);
}

View example | Packed | Back to top

Geocode

You can get the coordinates of a location by passing itss address or other descriptions. You can use ArcGISGeocodeService's findAddressCandidates method. You can dynamically construct an input form based on the meta data of the GeocodeService such as 'addressFields' property.

var inputs = { };
var fields=geocoder.addressFields;
for (var i=0; i < fields.length; i++){
  inputs[fields[i].name]=document.getElementById(fields[i].name).value;
}
geocoder.findAddressCandidates({inputs: inputs}, function(results) {
  var markers = [];
  if (results.candidates) {
    for (var i = 0, c = results.candidates.length; i < c; i++) {
      var marker=createMarker(results.candidates[i]);
      map.addOverlay(marker);
      markers.push(marker);
      if (i == 0) {
        map.setCenter(marker.getLatLng(),15);
        GEvent.trigger(marker, 'click');
      }
    }
  }
});

View example | Packed | Back to top

Reverse Geocode

You can also find the address of a given geographic coordinates (reverse geocode), using GeocodeService's reverseGeocode method.

function reverseGeocode(latlng){
  if (latlng){
    var point = ArcGISUtil.fromLatLngToPoint(latlng);
    var params = {
      location: point,
      distance: 100
    };
    geocoder.reverseGeocode(params, function(result) {
      if (result.address) {
        var html = '';
        var attrs = result.address;
        for (var x in attrs) {
          if (attrs.hasOwnProperty(x)) {
            html += x +': '+ attrs[x] + '<br/>';
          }
        }
        var loc=ArcGISUtil.fromPointToLatLng(result.location);
        marker.setLatLng(loc);
        marker.openInfoWindowHtml(html);
      } else { 
        alert('can not find address for point:'+latlng.toString());
      }
    });
  }            
}

View example | Packed | Back to top