4

There is a function in my map that works very nicely for zooming to a polygon (parcel) that has been selected:

_zoomToParcel: function(parcel) {
  this.map.setExtent(parcel.geometry.getExtent().expand(1.5));
}

The end user has requested that the zoom level be restricted to no more than 18. If it's a very small parcel, the zoom level may be 19 or 20, and then they have to zoom back out to find enough surroundings to orient themselves. Fair enough. I thought this would be as simple as adding in a get/set zoom:

_zoomToParcel: function(parcel) {
  this.map.setExtent(parcel.geometry.getExtent().expand(1.5));
  if (this.map.getZoom() > 18) {
    this.map.setZoom(18);
  }
}

However, this appears to be getting the zoom level from before the application resets the extent to the parcel. When I console.log the results of this.map.getZoom(), it tells me the initial zoom level (5), not the new zoom level (20) after the extent is reset. Running that function if the map starts off very zoomed-in (e.g. 20) will zoom it back out to 18, meaning the get/set logic works — I'm just not getting the "right" zoom.

How can I catch whether the map has zoomed in too far?

2 Answers 2

4

Try waiting for the extent-change event to fire.

http://jsbin.com/sapuxelepa/edit?html,output

  var map;

  require(["esri/map", "dojo/domReady!"], function(Map) {
    map = new Map("map", {
      basemap: "topo",  
      center: [-122.45, 37.75], // longitude, latitude
      zoom: 13
    });
    var extentListener = map.on("extent-change",function(evt)
      {
        console.log("extent change",evt.lod);
        if(evt.lod.level > 13)
          map.setZoom(13);


        extentListener.remove();
      }
    );
  });
1
  • This should work, as long as I can have it only watching for the extent change within that function (in regular pan/zoom operation, they want to be able to go in > 18). At minimum, this gives me a good direction to research.
    – Erica
    Commented Nov 4, 2015 at 20:18
2

@Kirk's answer works and is simple, but I didn't like that it would zoom all the way in and then zoom out a little.

The method I can up with is to find the map extent at the smallest scale and compare that to my extent. If my extent is larger, then I can safely zoom to extent. If my extent is smaller, then I zoom to whatever zoom level desired.

...

    const buffer = 1.05;
    const isGraphicsOverflowMinMapExtent = await this.isGraphicsOverflowMinMapExtent(
      map,
      graphics,
      buffer,
    );

    if (isGraphicsOverflowMinMapExtent) {
      map.setExtent(graphicsExtent);
      return;
    } else {
      map.centerAndZoom(graphicsCenterPoint, DEFAULT_ZOOM_LEVEL);
    }

...
  /**
   *Determines if the extents of an array of graphics is larger than the map extent at the max
   *scale returns true if the graphics are larger than the map extent. A buffer is used to
   *avoid graphics from being split
   *@returns True if the graphics extent is larger than the minimum map extent; otherwise, false
   */
  public async isGraphicsOverflowMinMapExtent(
    map: any,
    graphics: any[],
    buffer: number,
  ): Promise<boolean> {
      require([
        'esri/graphicsUtils',
        'esri/geometry/scaleUtils',
        'esri/geometry/webMercatorUtils',
        'esri/geometry/Extent',
        'esri/SpatialReference',
      ], ([graphicsUtils, scaleUtils, webMercatorUtils, Extent, SpatialReference] => {
        const graphicsExtent = graphicsUtils.graphicsExtent(graphics);

        const mapExtentAtMinScale = scaleUtils
          .getExtentForScale(map, map.getMaxScale())
          .setSpatialReference({ wkid: 4326 });

        const [minXmin, minYmin] = webMercatorUtils.xyToLngLat(
          mapExtentAtMinScale.xmin,
          mapExtentAtMinScale.ymin,
        );

        const [minXmax, minYmax] = webMercatorUtils.xyToLngLat(
          mapExtentAtMinScale.xmax,
          mapExtentAtMinScale.ymax,
        );

        const minDeltaX = Math.abs(minXmax - minXmin) * buffer;
        const minDeltaY = Math.abs(minYmax - minYmin) * buffer;

        return graphicsExtent.getHeight() > minDeltaY || graphicsExtent.getWidth() > minDeltaX;
      });
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.