Мне удалось добавить в InfoBox, чтобы заставить его делать то, что я хотел, с небольшой помощью SmartInfoWindow. Это частично настраиваемое решение, поэтому вам может понадобиться настроить позиционирование. Вы просто захватываете позицию div каждого угла InfoBox, конвертируете эти углы обратно в широту / долготу, а затем захватываете границы карт и смотрите, находятся ли углы внутри границ. Если это не так, вы соответственно регулируете положение InfoBox в зависимости от того, какие углы находятся вне карты.
InfoBox.prototype.maybePanMap = function() {
// if we go beyond map, pan map
var map = this.getMap();
var projection = this.getProjection();
var bounds = map.getBounds();
if (!bounds) return;
// The dimension of the infowindow
var iwWidth = this.div_.offsetWidth;
var iwHeight = this.div_.offsetHeight;
// The offset position of the infowindow
var iwOffsetX = this.pixelOffset_.width;
var iwOffsetY = this.pixelOffset_.height;
var anchorPixel = projection.fromLatLngToDivPixel(this.getPosition());
var bl = new google.maps.Point(anchorPixel.x + iwOffsetX,
anchorPixel.y + iwOffsetY);
var br = new google.maps.Point(anchorPixel.x + iwOffsetX + iwWidth,
anchorPixel.y + iwOffsetY);
var tl = new google.maps.Point(anchorPixel.x + iwOffsetX,
anchorPixel.y + iwOffsetY - iwHeight + 100);
var tr = new google.maps.Point(anchorPixel.x + iwOffsetX + iwWidth,
anchorPixel.y + iwOffsetY - iwHeight + 100);
var sw = projection.fromDivPixelToLatLng(bl);
var se = projection.fromDivPixelToLatLng(br);
var nw = projection.fromDivPixelToLatLng(tl);
var ne = projection.fromDivPixelToLatLng(tr);
if (!map.getBounds().contains(nw) && !map.getBounds().contains(sw)) {
this.div_.style.left = (anchorPixel.x + 10) + 'px';
if (!map.getBounds().contains(ne)) {
this.div_.style.top = (anchorPixel.y - 100) + 'px';
}
} else if (!map.getBounds().contains(nw) && !map.getBounds().contains(ne)) {
this.div_.style.top = (anchorPixel.y - 100) + 'px';
if (!map.getBounds().contains(se)) {
this.div_.style.left = (anchorPixel.x - iwWidth - 10) + 'px';
}
} else if (!map.getBounds().contains(ne) && !map.getBounds().contains(se)) {
this.div_.style.left = (anchorPixel.x - iwWidth - 10) + 'px';
if (!map.getBounds().contains(sw)) {
this.div_.style.top = (anchorPixel.y - iwHeight - 100) + 'px';
}
}
};