2011-05-05 8 views
6

J'ai utilisé du code de http://gmaps-samples-v3.googlecode.com/svn/trunk/infowindow_custom/infowindow-custom.html, qui est actuellement le meilleur exemple de Google pour créer des InfoWindow personnalisés dans Maps API v3. Je travaillais là-dessus et jusqu'à présent, je suis proche de travailler, sauf pour une chose, le contenu du texte ne s'étendra pas au contenu de div conteneur, donc il tombe juste au lieu d'élargir la bulle. Si je donne au conteneur de contenu une largeur de pixels fixe, cela fonctionne bien, mais je ne peux pas l'agrandir en fonction de la quantité de texte qu'il contient.CSS Google Maps Custom InfoWindow

J'ai été bloqué sur celui-ci pendant un moment. Toute aide serait grandement appréciée!

Voici la page HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<head> 
<title>Gayborhood Map Test</title> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> 
<style type="text/css"> 
    html { height: 100% } 
    body { height: 100%; margin: 0px; padding: 0px } 
    #map_canvas { width: 900px; 
    height: 400px; 
    margin: 200px auto 0 auto; } 
</style> 
<link rel="stylesheet" type="text/css" href="map.css" /> 
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> 
<script type="text/javascript" src="InfoBox.js"></script> 
<script type="text/javascript"> 
    function initialize() { 
    var latlng = new google.maps.LatLng(39.947137,-75.161824); 
    var myOptions = { 
     zoom: 16, 
     center: latlng, 
     mapTypeId: google.maps.MapTypeId.HYBRID 
    }; 

    var gayborhood; 

    var map = new google.maps.Map(document.getElementById("map_canvas"), 
     myOptions); 

    var gayborhoodcoords = [ 
     new google.maps.LatLng(39.9492017, -75.1631272), 
     new google.maps.LatLng(39.945423, -75.1639561), 
     new google.maps.LatLng(39.9450064, -75.160579), 
     new google.maps.LatLng(39.9487765, -75.1597468), 
     new google.maps.LatLng(39.9492017, -75.1631272) 
    ]; 

    gayborhood = new google.maps.Polygon({ 
     paths: gayborhoodcoords, 
     strokeColor: "#00ff00", 
     strokeOpacity: 0.8, 
     strokeWeight: 2, 
     fillColor: "#00ff00", 
     fillOpacity: 0.35 
    }); 

    gayborhood.setMap(map); 

    var image = 'red_icon.png'; 
    var myLatLng = new google.maps.LatLng(39.948883,-75.162246); 
    var redMarker = new google.maps.Marker({ 
     position: myLatLng, 
     map: map, 
     icon: image 
    }); 

    var contentString = '<h4>Woody\'s Bar</h4>'; 

    /*var infowindow = new google.maps.InfoWindow({ 
    content: contentString, 
    disableAutoPan: true 
    });*/ 

    google.maps.event.addListener(redMarker, 'mouseover', function() { 
     var infoBox = new InfoBox({marker: redMarker, map: map}); 
    }); 
    /*google.maps.event.addListener(redMarker, 'mouseout', function() { 
     infowindow.close(); 
    });*/ 
    } 

</script> 
</head> 
<body onload="initialize()"> 
    <div id="map_canvas"></div> 
</body> 
</html> 

Voici les InfoBox.js:

/* An InfoBox is like an info window, but it displays 
* under the marker, opens quicker, and has flexible styling. 
* @param {GLatLng} latlng Point to place bar at 
* @param {Map} map The map on which to display this InfoBox. 
* @param {Object} opts Passes configuration options - content, 
* offsetVertical, offsetHorizontal, className, height, width 
*/ 
function InfoBox(opts) { 
    google.maps.OverlayView.call(this); 
    this.marker_ = opts.marker 
    this.latlng_ = opts.marker.getPosition(); 
    this.map_ = opts.map; 
    this.offsetVertical_ = -65; 
    this.offsetHorizontal_ = -20; 
    this.height_ = 50; 
    //this.width_ = 159; 

    var me = this; 
    this.boundsChangedListener_ = 
    google.maps.event.addListener(this.map_, "bounds_changed", function() { 
     return me.panMap.apply(me); 
    }); 

    // Once the properties of this OverlayView are initialized, set its map so 
    // that we can display it. This will trigger calls to panes_changed and 
    // draw. 
    this.setMap(this.map_); 
} 

/* InfoBox extends GOverlay class from the Google Maps API 
*/ 
InfoBox.prototype = new google.maps.OverlayView(); 

/* Creates the DIV representing this InfoBox 
*/ 
InfoBox.prototype.remove = function() { 
    if (this.div_) { 
    this.div_.parentNode.removeChild(this.div_); 
    this.div_ = null; 
    } 
}; 

/* Redraw the Bar based on the current projection and zoom level 
*/ 
InfoBox.prototype.draw = function() { 
    // Creates the element if it doesn't exist already. 
    this.createElement(); 
    if (!this.div_) return; 

    // Calculate the DIV coordinates of two opposite corners of our bounds to 
    // get the size and position of our Bar 
    var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_); 
    if (!pixPosition) return; 

    // Now position our DIV based on the DIV coordinates of our bounds 
    //this.div_.style.width = this.width_ + "px"; 
    this.div_.style.left = (pixPosition.x + this.offsetHorizontal_) + "px"; 
    this.div_.style.height = this.height_ + "px"; 
    this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px"; 
    this.div_.style.display = 'block'; 
}; 

/* Creates the DIV representing this InfoBox in the floatPane. If the panes 
* object, retrieved by calling getPanes, is null, remove the element from the 
* DOM. If the div exists, but its parent is not the floatPane, move the div 
* to the new pane. 
* Called from within draw. Alternatively, this can be called specifically on 
* a panes_changed event. 
*/ 
InfoBox.prototype.createElement = function() { 
    var panes = this.getPanes(); 
    var div = this.div_; 
    if (!div) { 
    // This does not handle changing panes. You can set the map to be null and 
    // then reset the map to move the div. 
    div = this.div_ = document.createElement("div"); 
    div.className = "infobox"; 
    //div.style.width = this.width_ + "px"; 
    //div.style.height = this.height_ + "px"; 
    var leftDiv = document.createElement("div"); 
    leftDiv.className = "bubbleLeftDiv"; 
    var containerDiv = document.createElement("div"); 
    containerDiv.className = "infoboxContainer"; 
    var contentDiv = document.createElement("div"); 
    contentDiv.className = "infoboxContent"; 

    var title = "Much longer title than woody's" 

    //var infoboxWidth = (title.length*10 - (title.length) - 40) + "px" 
    //containerDiv.style.width = infoboxWidth; 
    //this.width_ = infoboxWidth + 47; 
    contentDiv.innerHTML = "<h3>" + title + "</h3>"; 
    var rightDiv = document.createElement("div"); 
    rightDiv.className = "bubbleRightDiv"; 

    function removeInfoBox(ib) { 
     return function() { 
     ib.setMap(null); 
     }; 
    } 

    google.maps.event.addListener(this.marker_, 'mouseout', removeInfoBox(this)); 

    div.appendChild(leftDiv) 
    div.appendChild(containerDiv); 
    containerDiv.appendChild(contentDiv); 
    div.appendChild(rightDiv); 
    div.style.display = 'none'; 
    panes.floatPane.appendChild(div); 
    this.panMap(); 
    } else if (div.parentNode != panes.floatPane) { 
    // The panes have changed. Move the div. 
    div.parentNode.removeChild(div); 
    panes.floatPane.appendChild(div); 
    } else { 
    // The panes have not changed, so no need to create or move the div. 
    } 
} 

/* Pan the map to fit the InfoBox. 
*/ 
InfoBox.prototype.panMap = function() { 
    // if we go beyond map, pan map 
    var map = this.map_; 
    var bounds = map.getBounds(); 
    if (!bounds) return; 

    // The position of the infowindow 
    var position = this.latlng_; 

    // The dimension of the infowindow 
    var iwWidth = this.width_; 
    var iwHeight = this.height_; 

    // The offset position of the infowindow 
    var iwOffsetX = this.offsetHorizontal_; 
    var iwOffsetY = this.offsetVertical_; 

    // Padding on the infowindow 
    var padX = 40; 
    var padY = 40; 

    // The degrees per pixel 
    var mapDiv = map.getDiv(); 
    var mapWidth = mapDiv.offsetWidth; 
    var mapHeight = mapDiv.offsetHeight; 
    var boundsSpan = bounds.toSpan(); 
    var longSpan = boundsSpan.lng(); 
    var latSpan = boundsSpan.lat(); 
    var degPixelX = longSpan/mapWidth; 
    var degPixelY = latSpan/mapHeight; 

    // The bounds of the map 
    var mapWestLng = bounds.getSouthWest().lng(); 
    var mapEastLng = bounds.getNorthEast().lng(); 
    var mapNorthLat = bounds.getNorthEast().lat(); 
    var mapSouthLat = bounds.getSouthWest().lat(); 

    // The bounds of the infowindow 
    var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX; 
    var iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX; 
    var iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY; 
    var iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY; 

    // calculate center shift 
    var shiftLng = 
     (iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) + 
     (iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0); 
    var shiftLat = 
     (iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) + 
     (iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0); 

    // The center of the map 
    var center = map.getCenter(); 

    // The new map center 
    var centerX = center.lng() - shiftLng; 
    var centerY = center.lat() - shiftLat; 

    // center the map to the new shifted center 
    map.setCenter(new google.maps.LatLng(centerY, centerX)); 

    // Remove the listener after panning is complete. 
    google.maps.event.removeListener(this.boundsChangedListener_); 
    this.boundsChangedListener_ = null; 
}; 

Et voici le CSS:

.infobox { 
    border: 0px none; 
    position: absolute; 
    width: auto; 
    height: auto; 
} 

.infoboxContent { 
    font-family: arial, helvetica, sans-serif; 
    font-size: 15px; 
    padding: 0px; 
    margin: 9px 0px 0px -24px; 
    position: absolute; 
    z-index: 105; 
} 

.infoboxContainer { 
    background: url('infowindow_bg.png') repeat-x; 
    height: 50px; 
    margin-left: 47px; 
} 

.bubbleLeftDiv { 
    width: 47px; 
    height: 50px; 
    background: url('infowindow_left.png') no-repeat; 
    position: absolute; 
    z-index: 102; 
} 

.bubbleRightDiv { 
    width: 26px; 
    height: 50px; 
    background: url('infowindow_right.png') no-repeat; 
    position: absolute; 
    right: -26px; 
    top: 0px; 
} 

.clear { clear: both; } 

Merci !!

+0

problème très similaire à celui discuté ici: http://stackoverflow.com/questions/1554893/google -maps-api-v3-infowindow-not-dimensionnement-correctement –

Répondre

3

J'ai rencontré le même problème. L'approche qui a fonctionné pour moi était de déterminer dynamiquement les dimensions du contenu et de définir la hauteur et la largeur de l'InfoBox correctement. Le problème que j'ai rencontré avec ceci était qu'avant que le contenu soit inséré dans le DOM il n'a pas (correct) des valeurs de dimension. Par conséquent mon approche est la suivante:

  1. Créer l'élément contenu DOM qui doit être inséré
  2. Insérez dans un récipient de température
  3. Obtenez les dimensions de l'emballage temporaire
  4. Supprimer conteneur temp
  5. Insérer du contenu dans InfoBox et définir sa hauteur et sa largeur en fonction des dimensions du conteneur temp

Voici un exemple réalisé avec le framework jQuery:

var temp = $("<div class='temp'></div>").html(content).hide().appendTo("body"); 
    var dimentions = { 
     width : temp.outerWidth(true), 
     height : temp.outerHeight(true) 
    }; 
    temp.remove(); 

    var overlayProjection = this.getProjection(); 
    var top_left = overlayProjection.fromLatLngToDivPixel(this.point_);   

    var dimensions= $.extend({}, dimensions, { 
     y : top_left.y - dimensions.height, 
     x : top_left.x - dimensions.width/2 
    }); 

    var div = this.div_; 
    $(div).css({ 
     "top": dimensions.y + 'px', 
     "left" : dimensions.x + 'px', 
     "width" : dimensions.width + 'px', 
     "height" : dimensions.height + 'px' 
    }).html(content); 

Espérons que ça aide!

0

Vous pouvez remplacer la méthode de la draw infobox et repositionner le Infobox après qu'il a été rendu:

var infobox = new InfoBox(myOptions); 
infobox.initReady = false; 
var oldDraw = infobox.draw; 
infobox.draw = function() { 
    oldDraw.apply(this); 
    if(! infobox.initReady) { 

    // Calculate the required offset 
    var offsetY = -($(infobox.div_).outerHeight()); 
    var offsetX = -110; 
    infobox.initReady = true; 

    // Set the new pixelOffset 
    infobox.setOptions({ 
     pixelOffset: new google.maps.Size(offsetX, offsetY) 
    }); 
    } 
}