2

I want to limit map extent to the initial extent of the map and limit user from panning more than certain extent.

I tried following but nothing has changed:

map = new Map( "map" , {
        basemap: "gray",    
        center: [-85.416, 49.000],
        zoom : 6,
        logo: false,
        sliderStyle: "small"
    });


    dojo.connect(map, "onExtentChange", function (){
    var initExtent = map.extent;
    var extent = map.extent.getCenter();
    if(initExtent.contains(extent)){}
    else{map.setExtent(initExtent)}
    });
Vikash Pandey
  • 5,407
  • 6
  • 41
  • 42
John Macl
  • 331
  • 2
  • 5
  • 12
  • 1
    I would update your question's title to better reflect your actual question. It looks like you want to manually pan the map, but you really want to restrict the user's ability to pan the map. – Aaron Mar 18 '14 at 18:38
  • Hi Aaron , I have tested your code on this link:http://jsfiddle.net/bbunker/JP565/ but it keeps going to infinite loop in if (outOfBounds) section. How can I avoid this? – John Macl Mar 21 '14 at 22:39
  • John, my approach was not exactly the best. It wouldn't restrict panning. The better approach would be use those initializer properties, then set maximum extent, and on the map's onExtentChanged make sure the map's extent hasn't gone outside the maximum you set. – Aaron Mar 22 '14 at 00:06

3 Answers3

2

Just to flesh out Simon's answer somewhat, and give an example. Ideally you need two variables at the same scope as map:

initExtent to store the boundary of your valid extent, and

validExtent to store the last valid extent found while panning, so that you can bounce back to it.

I've used the newer dojo.on event syntax as well for this example, it's probably a good idea to move to this as per the documentation's recommendation - I assume ESRI will discontinue the older style at some point.

var map;
var validExtent;
var initExtent;

[...]

    require(['dojo/on'], function(on) {
        on(map, 'pan', function(evt) {
            if ( !initExtent.contains(evt.extent) ) {
                console.log('Outside bounds!');
            } else {
                console.log('Updated extent');
                validExtent = evt.extent;
            }
        });

        on(map, 'pan-end', function(evt) {
            if ( !initExtent.contains(evt.extent) ) {
                map.setExtent(validExtent);
            }
        });
    });

You can do the same with the zoom events, or use extent-change if you want to trap everything. Up to you.

Juffy
  • 1,220
  • 13
  • 22
  • I used your approach and it works well except one thing. It infinitely loads after pan ends. How can I solve this issue. – John Macl Mar 20 '14 at 18:13
  • Hmmm...I can't replicate that - mine fires a `pan-end`, a series of `pan`s as it slides back to `validExtent`, then another `pan-end`. Tested in IE9 and Chrome. – Juffy Mar 21 '14 at 00:59
1

It looks like your extent changed function is setting the initial extent variable to the maps current extent and then checking if that extent contains the current extents centre point - which of course it always will.

Instead, declare initExtent at the same scope of the map variable. Then, change the on load event to set this global scope variable rather than a local variable. In the extent changed function, don't update the value of initExtent, simply check the initExtent contains the entire of the current extent.

Alternatively you could compare each bound of the current extent to each bound of the initExtent, e.g. is initExtent.xmin < map.extent.xmin and if any are, create a new extent setting any exceeded bounds to the initExtent values.

The only problem is these techniques will allow the initExtent to be exceeded briefly, but will then snap the extent back once the extent changed function fires and catches up.

Kate
  • 1,556
  • 1
  • 16
  • 33
0

I originally posted this solution on gis.stackexchange in answer to this question: https://gis.stackexchange.com/a/199366

Here's a code sample from that post:

//This function limits the extent of the map to prevent users from scrolling 
//far away from the initial extent.
function limitMapExtent(map) {
    var initialExtent = map.extent;
    map.on('extent-change', function(event) {
        //If the map has moved to the point where it's center is 
        //outside the initial boundaries, then move it back to the 
        //edge where it moved out
        var currentCenter = map.extent.getCenter();
        if (!initialExtent.contains(currentCenter) && 
            event.delta.x !== 0 && event.delta.y !== 0) {

            var newCenter = map.extent.getCenter();

            //check each side of the initial extent and if the 
            //current center is outside that extent, 
            //set the new center to be on the edge that it went out on
            if (currentCenter.x < initialExtent.xmin) {
                newCenter.x = initialExtent.xmin;
            }
            if (currentCenter.x > initialExtent.xmax) {
                newCenter.x = initialExtent.xmax;
            }
            if (currentCenter.y < initialExtent.ymin) {
                newCenter.y = initialExtent.ymin;
            }
            if (currentCenter.y > initialExtent.ymax) {
                newCenter.y = initialExtent.ymax;
            }
            map.centerAt(newCenter);
        }
    });
}

And here's a working jsFiddle example: http://jsfiddle.net/sirhcybe/aL1p24xy/

Community
  • 1
  • 1
Chris
  • 1,978
  • 3
  • 23
  • 35