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:
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:
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– KHibma2019年12月19日 14:01:14 +00:00Commented Dec 19, 2019 at 14:01
-
Sorry, I should have mentionned its 3.xBelow the Radar– Below the Radar2019年12月19日 23:16:39 +00:00Commented Dec 19, 2019 at 23:16
-
Are the units of the map and panel the same?whyzar– whyzar2020年01月06日 20:45:38 +00:00Commented Jan 6, 2020 at 20:45
-
The map units are in meters but the panel is in pixelBelow the Radar– Below the Radar2020年01月06日 20:57:46 +00:00Commented Jan 6, 2020 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– Mayur Shinde2020年01月07日 11:38:48 +00:00Commented Jan 7, 2020 at 11:38
2 Answers 2
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.
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;
}
-
Hi! thank you, but I am looking for a one shot function. Also, your codePen is not working.Below the Radar– Below the Radar2020年01月07日 20:41:56 +00:00Commented Jan 7, 2020 at 20:41
-
1It took me some time to re organize my answer. I hope it can help you.NettaB– NettaB2020年01月07日 22:48:49 +00:00Commented Jan 7, 2020 at 22:48