9

I'm working on a site that makes use of v7 of the Bing Maps AJAX Control. One of the things I need to do is restrict the zoom level so as to prevent users from zoom in past a certain level, or zoom out past a certain level.

I found a "getZoomRange" method on the Map object, after inspecting it, it simply returns an object literal with "min" and "max" properties. So, I figured overloading it would probably do the trick:

// "map" is our Bing Maps object
map.getZoomRange = function ()
{
  return {
    max:      14
    min:      5
  };
};

...but no. It has no effect (it actually has something to do with the appearance of the zoom slider when using the default Dashboard).

Hijacking the event and preventing it from proceeding also seems to have no effect.

rbrundritt
  • 16,570
  • 2
  • 21
  • 46
BenLanc
  • 2,344
  • 1
  • 19
  • 24

3 Answers3

10

I was dealing with a similar issue and I ended up doing something very similar to what MrJamin describes in his answer, with one (subtle, but major) difference: I added a handler for targetviewchanged. According to the official docs on MSDN, 'targetviewchanged' occurs when the view towards which the map is navigating changes. Also, instead of calling Map#getZoom, I used Map#getTargetZoom which returns the zoom level of the view to which the map is navigating. Note, this approach prevents jitter.

Here's the shortened version of my code:

function restrictZoom(map,min,max) {
  Microsoft.Maps.Events.addHandler(map,'targetviewchanged',function(){
    var targetZoom = map.getTargetZoom();
    var adjZoom = targetZoom;

    if(targetZoom > max) {
      adjZoom = max;
    } else if(targetZoom < min) {
      adjZoom = min;
    }

    if(targetZoom != adjZoom) {
      map.setView({zoom:adjZoom});
    }
  });
}
Andrey
  • 8,882
  • 10
  • 58
  • 82
  • So this seems to work but makes the map "bounce" if they zoom out using the mouse wheel, and if they spam it enough they break out of the min/max zoom. Any suggestions? – Aleski May 19 '15 at 10:54
10

According to Bing Maps support, the only way to do this (which isn't particularly elegant, and results in some unwelcome jitter on the map) is as follows:

// "map" is our Bing Maps object, overload the built-in getZoomRange function
// to set our own min/max zoom
map.getZoomRange = function ()
{
  return {
    max:      14,
    min:      5
  };
};

// Attach a handler to the event that gets fired whenever the map's view is about to change
Microsoft.Maps.Events.addHandler(map,'viewchangestart',restrictZoom);

// Forcibly set the zoom to our min/max whenever the view starts to change beyond them 
var restrictZoom = function ()
{
  if (map.getZoom() <= map.getZoomRange().min) 
  {
    map.setView({
      'zoom':       map.getZoomRange().min,
      'animate':    false
    });
  }
  else if (map.getZoom() >= map.getZoomRange().max) 
  {
    map.setView({
      'zoom':       map.getZoomRange().max,
      'animate':    false
    });
  }
};
Chase Florell
  • 46,378
  • 57
  • 186
  • 376
BenLanc
  • 2,344
  • 1
  • 19
  • 24
  • 4
    One of the reason updates to v7 of the Bing Maps API kind of sort of broke this. It still works properly in most cases, but if a user aggressively zooms in or out using their mouse wheel, the "viewchangestart" event doesn't always catch this properly. My fix was to call the "restrictZoom" function on both the "viewchangestart" and "viewchange" event. I also do not check for the if the zoom is ">=" or "<="; I, rather, check if the zoom is ">" or "<". This works best out of all of the examples I've found. – Nate Irwin Dec 17 '11 at 22:48
  • 1
    This is not working for me in v8 of the Bing Maps API – J86 Nov 24 '16 at 11:19
0

Another way to achieve this is to handle the event thrown when the mouse wheel is moved. http://msdn.microsoft.com/en-us/library/gg427609.aspx

When you handle the mousewheel event, you can check whether the mouse wheel is being scrolled forwards or backwards, and then check the map.targetZoom() in order to compare with a min or max zoom value. If the min or max are exceeded, then set event.handled = true. This prevents the event from being handled by any other handlers which prevents default behaviour. From the documentation:

A boolean indicating whether the event is handled. If this property is set to true, the default map control behavior for the event is cancelled.

See below:

var Zoom = {
    MAX: 10,
    MIN: 2
}

var mouseWheelHandler = function(event) {

    // If wheelDelta is greater than 0, then the wheel is being scrolled forward which zooms in
    if(event.wheelDelta > 0) {
        if(map.getTargetZoom() >= Zoom.MAX) {
            event.handled = true;
        }                        
    }
    else {
        if(map.getTargetZoom() <= Zoom.MIN) {
            event.handled = true;
        }

    }
}

Microsoft.Maps.Events.addHandler(map, 'mousewheel', mouseWheelHandler);
mricci
  • 953
  • 1
  • 7
  • 13