javascriptesri-mapsesri-javascript-api

ESRI Maps setting MapView.extent cuts off top and bottom of extent in display


I have an ESRI map that I initialize with a given extent. When I draw the map with its initial extent, the extent of what is actually displayed is cut off by about 5-10%, so some features on my FeatureLayers lie outside the initial view. It seems like the map is trying to form a "best fit" zoom level to match the requested extent to the map size, but in this case, the best fit leaves the top and bottom of the view cropped off.

I created a demo to show this behavior:

const map = new EsriMap({
  basemap: 'topo',
});
const extent = {
  spatialReference: {
    latestWkid: 3857,
    wkid: 102100,
  },
  xmin: -8418477.75984,
  ymin: 5691645.413467902,
  xmax: -8413622.645963104,
  ymax: 5694628.596517603,
};

const mapView = new EsriMapView({
  container: document.querySelector('#viewDiv'),
  extent,
  map,
});

const geometry = new EsriPolygon({
  rings: [
    [extent.xmax, extent.ymax],
    [extent.xmax, extent.ymin],
    [extent.xmin, extent.ymin],
    [extent.xmin, extent.ymax],
    [extent.xmax, extent.ymax],
  ],
  spatialReference: extent.spatialReference,
});

const symbol = {
  type: 'simple-line',
  color: [255, 0, 0],
  width: 2,
};

const graphic = new EsriGraphic({
  geometry,
  symbol,
});

mapView.graphics.add(graphic);

See live at https://codepen.io/asgallant/pen/rrWmLW. The red box is the requested extent. If you change the height of the map's container, the map changes its initial zoom level at certain break points.

I would like to configure the map to always choose a default zoom level that fully encapsulates the requested extent, so no features are cut off. I know I can just set the zoom level to whatever I want, but I have hundreds of different maps, requiring different zoom levels to achieve the stated goal. Does anyone know how to accomplish this?


Solution

  • You can use when callback to check if map's extent contains your required extent. If your expected extent is outside map's extent's boundary you just zoom-out.

    You can check your posted example working here.

    mapView.when(function(){
        if(!mapView.extent)
          return;
    
        const ext = new EsriExtent(extent);    
        while(mapView.zoom > 0 && !mapView.extent.contains(ext)) {
          mapView.zoom -= 0.5;
        }
    });