knisleyj

map.setExtent() bug

Discussion created by knisleyj on Mar 28, 2012
Latest reply on Apr 6, 2012 by DSwingley-esristaff
Several months ago I made a post similar to this on the forums for the ArcGIS API for Android.  I'm now exploring mobile web apps using Javascript instead, and discovered what appears to be a bug in the setExtent() method.  I'm using this method to zoom the map into an extent which includes the user's location and a selected destination including a small buffer.

When you specify the boundaries for the extent, a logical assumption is that a rectangle will be created which contains, at a minimum, the points xmin,ymin and xmax,ymax.  Obviously the parameters given may need to be adjusted to accommodate the current map dimensions, but this does not happen correctly in some cases.  In its current implementation setExtent() creates an extent which encompasses the x-boundaries, but not necessarily the y-boundaries.

For the following examples I'll refer to dx (xmax-xmin) and dy (ymax-ymin).  If dx is large relative to dy (for example, the user selects a point that is west or east of their current location), then then ymax and ymin are adjusted as needed and the map zooms appropriately.  On the other hand, if dx is very small relative to dy (for example, the user selects a point that is north or south of their current location), then the map zooms in much too close.  It sets the x borders at xmin and xmax, but ymin and ymax are placed off of the screen.

Below is code that I currently use as a workaround.  It assumes the device is in portrait mode, but could easily be modified to handle screens of various dimensions.

function zoomToPoints(point1, point2) {
 var xmin, ymin, xmax, ymax;
 
 if (point1.x < point2.x) {
  xmin = point1.x;
  xmax = point2.x;
 } else {
  xmin = point2.x;
  xmax = point1.x;
 }
 if (point1.y < point2.y) {
  ymin = point1.y;
  ymax = point2.y;
 } else {
  ymin = point2.y;
  ymax = point1.y;
 }
 
 // add buffer to envelope so that points aren't on the edge of the screen
 var xBuffer = (xmax - xmin) * 0.2;
 var yBuffer = (ymax - ymin) * 0.4;
 xmax += xBuffer;
 xmin -= xBuffer;
 ymax += yBuffer;
 ymin -= yBuffer;
 
 // to zoom appropriately under the current API, dY/dX should be approximately 127/80 based on emulator experiments in portrait mode
 // if dX is small then it needs to be adjusted based on dY before calling setExtent()
 if ((ymax-ymin) / (xmax-xmin) > 127.0/80.0) {
  var dX = 80.0 * (ymax-ymin) / 127.0; 
  xmax = ((xmax+xmin)/2.0) + (dX / 2.0);
  xmin = ((xmax+xmin)/2.0) - (dX / 2.0);
 }
 
 // set the map's new extent
    map.setExtent(new esri.geometry.Extent({
        "xmin": xmin,
        "ymin": ymin,
        "xmax": xmax,
        "ymax": ymax,
        "spatialReference": {
            "wkid": 102100
        }
    }));
}

Outcomes