Select to view content in your preferred language

problem map extent functions

1393
4
06-07-2012 05:56 AM
StephenTaylor
New Contributor
In using the JS API, I need to detect if the current extent matches the initial extent. If no match, then I need to display a UI element ("Return to Original Extent").

The initial extent is cached in a data store after the map loads (in my own object mapState.initialExtent). This is properly configured as an instance of an esri extent. I can trigger the map to move to this extent successfully.

I have created a listener on the map (onExtentChange) which calls a function which compares the current extent to the initial extent. It seems the best way to do this is to compare the x/y min/max which is fine and works *EXCEPT* that *BOTH* the return from the call to map.extent *AND* the extent return by the listener are inaccurate.

That is: if I do this:

// SET LISTENER ON MAP LOAD
dojo.connect(map, "onExtentChange", compareExtent)

// AT SOME TIME LATER DO THIS
map.setExtent(mapState.initialExtent) // this works

function compareExtent(extent, delta, levelChange, lod) {
// FAILS WHEN COMPARING THE FOLLOWING:
var currentExtent = map.extent;
var returnedExtent = extent;
var initialExtent = mapState.initialExtent;

console.log("currentExtent.xmin", currentExtent.xmin, "initialExtent.xmin", initialExtent.xmin, "extent.xmin", extent.xmin);
console.log("currentExtent.ymin", currentExtent.ymin, "initialExtent.ymin", initialExtent.ymin, "extent.ymin", extent.ymin);

//these do not match
//HERE IS THE CONSOLE READ OUT
currentExtent.xmin -8476373.507203963
initialExtent.xmin -8476287.515547141
extent.xmin -8476373.507203963

currentExtent.ymin 4412584.280379601
initialExtent.ymin 4412589.057693868
extent.ymin 4412584.280379601

}


So, I checked to see if this listener actually returns BEFORE the map is finished but it does not.

Anyone have ideas?

Thanks to all

S
0 Kudos
4 Replies
derekswingley1
Deactivated User
Instead of continuously comparing properties of extents, why not enable your "return to initial extent" button when onExtentChange initially fires? Since onExtentChange fires when the map's extent changes, by definition, you know that the new extent is not going to be equal to the map's initial extent.

I would then disconnect your listener for onExtentChange and only re-enable it when your "return to initial extent" button is clicked. I would also remove or disable your "return to initial extent" button after it's clicked as well.
0 Kudos
StephenTaylor
New Contributor
@ Swingley - thx for the timely repsonse and excellent suggest.

Here is the issue:

I set the map extent in the map options:
extent: new esri.geometry.Extent(-8476374.53057687,4412585.6098486995,-8467374.070496302, 4419828.01827871, new esri.SpatialReference({ wkid:102100 }))

Using a dojo deferred, the callback calls a makeMap function onMapLoad.

At the end of makeMap, after injecting a text div (for now) and setting that div style = display: none (in css), I add this:
(noting that I really hate that this seems to require a global variable  - that is, the variable "extentChangeListener" is set at the top of the script)

extentChangeListener = dojo.connect(map, "onExtentChange", function(extent, delta, levelChange, lod) {

console.log("extent.xmin", extent.xmin);

  $("#returnInitial").fadeIn(400, function() {
   dojo.disconnect(extentChangeListener);
  });
});

First Issue:
Note that this fires on map load (it should not, right?) and that on this initial firing the console reads:

extent.xmin -8476374.53057687

This is the correct value (as are the others) BUT why is this event firing?

So, what am I doing wrong here?

Second Issue:
For clarity: the user can turn on/off any of several layers, each of which triggers an extent change (this works).

I can see 1) hiding this UI on init and 2) embedding this listener on-off in these function

BUT I also need to listen for extent changes via zoom or pan.

I mean, where does this initial to listener go?

Thx

S
0 Kudos
TimRourke
Emerging Contributor
Stephen,

I'm pretty sure the geometry of the map div affects how the extent is set when you call map.setExtent(extent, fit?). The API should center your extent in the available area of the map unless you're locking down scales or levels of detail. After setting the extent, I expect the map object's extent property to contain the actual extent, not necessarily the one specified.

The maps we build here usually are not a fixed size, so our scripts confirm the initial map extent by setting it again after all the layers are loaded, because the map doesn't really finish loading until the first layer is added to the map. Just to be safe, after the initial extent is set, you could grab the current extent and store it to make sure if you still want to compare extents.

After the layers are loaded and the initial extent confirmed, we set up the onExtentChange event handler, and it catches all extent changes after that. But we don't do any later comparisons, because we just cache the extents so the user can go back and forth in the extent history.

I'm with you on the global variables. If you want to cut down on that, you can create one global object and store event handlers as members of that object. We wrote an EventHandler class to store layer event handlers on one array, map event handlers in another, and so on.
0 Kudos
HemingZhu
Frequent Contributor
Stephen,

I'm pretty sure the geometry of the map div affects how the extent is set when you call map.setExtent(extent, fit?). The API should center your extent in the available area of the map unless you're locking down scales or levels of detail. After setting the extent, I expect the map object's extent property to contain the actual extent, not necessarily the one specified.

The maps we build here usually are not a fixed size, so our scripts confirm the initial map extent by setting it again after all the layers are loaded, because the map doesn't really finish loading until the first layer is added to the map. Just to be safe, after the initial extent is set, you could grab the current extent and store it to make sure if you still want to compare extents.

After the layers are loaded and the initial extent confirmed, we set up the onExtentChange event handler, and it catches all extent changes after that. But we don't do any later comparisons, because we just cache the extents so the user can go back and forth in the extent history.

I'm with you on the global variables. If you want to cut down on that, you can create one global object and store event handlers as members of that object. We wrote an EventHandler class to store layer event handlers on one array, map event handlers in another, and so on.


How about use if (currentExtent.contains(initialExtent) && currentExtent.intersects(initialExtent))?
0 Kudos