John Macl
John Macl

Reputation: 331

Panning the map to certain extent javascript API

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)}
    });

Upvotes: 2

Views: 3066

Answers (3)

Chris
Chris

Reputation: 2046

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/

Upvotes: 0

Juffy
Juffy

Reputation: 1220

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.

Upvotes: 2

Kate
Kate

Reputation: 1576

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.

Upvotes: 1

Related Questions