3

I am trying to set map extent using an offset because there is a panel floating over the left side of the map and sometimes, when I zoom to a feature extent, the feature is partly hidden behind it.

I would like the extent to be always displayed and CENTERED in the map section that is not hidden by the panel

For instance the normal behavior is like below, but some of the feature is hidden behind the panel:

enter image description here

I would like to find a way to center the feature in the map section that is not hidden by the panel like the red rectangle below:

enter image description here

This is what I tried so far without success:

function zoomToExtent(extent) {
  var hiddenMapPartTopLeft = map.toMap(new ScreenPoint(0, 0)),
      hiddenMapPartBottomRight = map.toMap(new ScreenPoint(panel.position.left + panel.position.width, map.container.offsetHeight));

  var dx = new Extent({
    xmin: hiddenMapPartTopLeft.x,
    ymin: hiddenMapPartBottomRight.y,
    xmax: hiddenMapPartBottomRight.x,
    ymax: hiddenMapPartTopLeft.y,
    spatialReference: map.spatialReference
  }).getWidth();

  extent = extent.offset(dx, 0);
  map.setExtent(extent);
}

The map zoom way too far to the right.

Is there a solution for this?

  • Confirming: this is the 4.x API? – KHibma Dec 19 '19 at 14:01
  • Sorry, I should have mentionned its 3.x – Below the Radar Dec 19 '19 at 23:16
  • Are the units of the map and panel the same? – whyzar Jan 6 at 20:45
  • The map units are in meters but the panel is in pixel – Below the Radar Jan 6 at 20:57
  • If you are using Web AppBuilder (I believe it is Launcpad theme). One of a workaround could be to hide/minimize the 'LayerList' widget(floating panel), when you zoom to a feature extent. If possible you can switch to 'Tab' theme - which has a separate tab for rendering the widgets without floating on map area. – Mayur Shinde Jan 7 at 11:38
1

You were almost there. Here is the correct code.

function zoomToExtent(extent) {
  var hiddenMapPartTopLeft = map.toMap(new ScreenPoint(0, 0)),
      hiddenMapPartBottomRight = map.toMap(new ScreenPoint(panel.position.width, map.container.offsetHeight)); // Removed panel.postion.left

  var dx = new Extent({
    xmin: hiddenMapPartTopLeft.x,
    ymin: hiddenMapPartBottomRight.y,
    xmax: hiddenMapPartBottomRight.x,
    ymax: hiddenMapPartTopLeft.y,
    spatialReference: map.spatialReference
  }).getWidth();

  extent = extent.offset(-dx, 0); //shift to right with -dx and to left with +dx
  map.setExtent(extent);
}

Also see the jsfiddle here. The shift the map after searching a location, click on My custom search box: and anywhere on jsfiddle window.

|improve this answer|||||
0

My approach would be different - not to set the extent - just recenter the map after zooming to the desired geometry.

I've created a little codePen based on the geolocate example, which creates a point and zoom to it, it also zooms in the start on Eiffel tower

I've changed the example so there will be side and bottom divs, as in your map.

After the geolocation and zooming:
- Create new definitions for 'centered' map width and height
- Center the map to the new position - all based on screen points - since the map is already focused on the desired geometry - we just need to move the map center according to the side and bottom divs.

Note: since the polygon can be hidden by the panels - I've added a setZoom to current zoom level minus 3 (can be 1 as well I guess).
GL!

EDIT: In order to activate the example - click on the locate button OR wait 2 seconds.. EDIT2: Basically I created a function that recenters the map when needed - like your zoomToExtent. It recenters the map according to the x,y of the current screen. You will also want to change the zoom level, depends on the polygon

function centerMap(zoom) {

  // Get dimensions of side div
  var sideDiv = document.getElementById('sideDiv');      
  var centerdMapWidth = map.width - sideDiv.getBoundingClientRect().right;
  // Create centered screen X
  var centeredMapX = centerdMapWidth/2;

  // Get dimensions of bottom div
  var bottomDiv = document.getElementById('bottomDiv');         
  var centerdMapHeight = bottomDiv.getBoundingClientRect().top;
  // Create centered screen Y
  var centeredMapY = map.height - centerdMapHeight/2;

  // Create new center point
  var scrPoint = new ScreenPoint(centeredMapX, centeredMapY);         
  // Create the center point in map units
  var centeredMapPoint = screenUtils.toMapPoint(map.extent, map.width, map.height, scrPoint);
  //Zoom out (to polygons...)
  map.setZoom(map.getZoom() - 3)
  // Move to the new center
  // Added a timeout to see the difference between the points
    map.centerAt(centeredMapPoint);
    document.getElementById('sideDiv').innerHTML = "New center: " + centeredMapPoint.x + "<br>" +  centeredMapPoint.y;

}
|improve this answer|||||
  • Hi! thank you, but I am looking for a one shot function. Also, your codePen is not working. – Below the Radar Jan 7 at 20:41
  • 1
    It took me some time to re organize my answer. I hope it can help you. – NettaB Jan 7 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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