Demo: http://psousa.net/demos/bingmaps/infoBoxAutoPanModule/simpleExample.html
Basically there are two maps, both with a pushpin near the edge and a click handler to display an infobox.
After clicking the pushpins this is the end-result:
The first one shows the default behavior: the infobox is displayed, although outside the map boundaries.
The second one, using my module, pans the map so that the infobox is fully visible.
Usage:
Using this module is incredibly simple. Just load it as usual and run the InitInfoboxAutoPanModule command:
Then, just create an infobox, using the typical infobox.setOptions({visible: true}) to display it.
Now, here's the detail: I've created an additional parameter called "autoPan". Just add it to the previous command and the map should automatically pan if required:
And that's mostly it :)
I've also added an optional argument to the module initialization which allows the margin to the edge to be configured (default: 5x5). Thus, if for instance the module would be initialized as:
The end-result after panning would be:
Implementation:
Using this module is incredibly simple. Just load it as usual and run the InitInfoboxAutoPanModule command:
MM.registerModule("InfoboxAutoPanModule", "js/InfoboxAutoPanModule.js");
MM.loadModule("InfoboxAutoPanModule", { callback: function () {
    InitInfoboxAutoPanModule(map);
    //Rest of the code
}); 
Then, just create an infobox, using the typical infobox.setOptions({visible: true}) to display it.
Now, here's the detail: I've created an additional parameter called "autoPan". Just add it to the previous command and the map should automatically pan if required:
infobox.setOptions({visible: true, autoPan: true});
And that's mostly it :)
I've also added an optional argument to the module initialization which allows the margin to the edge to be configured (default: 5x5). Thus, if for instance the module would be initialized as:
InitInfoboxAutoPanModule(map,{horizontalPadding:50, verticalPadding:20});
The end-result after panning would be:
Implementation:
The implementation is also simple. I just copy the original setOptions function to a new field inside the infobox and redefine setOptions to include some extra code. Basically it's just an hook on the existing function:
this._oldSetOptions(arguments);
if(arguments.autoPan == true && arguments.visible == true) {
    var infobox = this;
    var mapWidth = _map.getWidth();
    var mapHeight = _map.getHeight();
    var point = _map.tryLocationToPixel(infobox.getLocation());
    var remainderX = (mapWidth / 2) - point.x;
    var remainderY = (mapHeight / 2) + point.y;
    //Empirical values based on the current infobox implementation
    var xExtraOffset = 33;
    var yExtraOffset = 37;
    var pixelsOutsideX = infobox.getWidth() + 
                         infobox.getOffset().x - remainderX - xExtraOffset + 
                         _options.horizontalPadding;
    
    var pixelsOutsideY = infobox.getHeight() + 
                         infobox.getOffset().y + yExtraOffset - remainderY + 
                         _options.verticalPadding;
    var newPoint = new Microsoft.Maps.Point(0, 0);
    if (pixelsOutsideX > 0) {
        newPoint.x += pixelsOutsideX;
    }
    if (pixelsOutsideY > 0) {
        newPoint.y -= pixelsOutsideY;
    }
    var newLocation = _map.tryPixelToLocation(newPoint);
    _map.setView({
        center: new MM.Location(newLocation.latitude, newLocation.longitude)
    });
}
Enjoy.



This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeletePedro I have a question on this - I am confused as to where to place the code for the autopan? Can you email me? Or can I email you my code? Sorry to bother you but I am new to JS. Thank you.
ReplyDeleteHi,
DeleteJust check my example above. It's quite simple: http://psousa.net/demos/bingmaps/infoBoxAutoPanModule/simpleExample.html