2011-05-05 4 views
6

http://gmaps-samples-v3.googlecode.com/svn/trunk/infowindow_custom/infowindow-custom.html의 코드를 사용하고 있습니다.이 코드는 현재 Maps API v3에서 맞춤 InfoWindow를 만드는 방법에 대한 Google의 가장 좋은 예입니다. 나는 그것에 대해 연구 해왔다. 지금까지 한 가지를 제외하고는 작업에 가까워졌다. div 컨테이너는 텍스트 내용이 내용에 맞게 확장되지 않으므로 거품을 확장하는 대신 그냥 떨어졌다. 콘텐츠 컨테이너에 고정 픽셀 너비를 지정하면 잘 작동하지만 그 안에있는 텍스트의 양에 따라 펼칠 수는 없습니다.CSS Google Maps 사용자 정의 InfoWindow

나는 한동안이 일에 매달 렸습니다. 어떤 도움이라도 대단히 감사하겠습니다!

/* 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; 
}; 

그리고 여기에 CSS의 :

여기 여기 InfoBox.js의 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> 

입니다

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

감사합니다!

+0

여기서 논의 된 것과 매우 비슷한 문제 : http://stackoverflow.com/questions/1554893/google -maps-api-v3-infowindow-not-sizing-correctly –

답변

3

동일한 문제에 직면했습니다. 나에게 도움이 된 접근 방식은 내용의 크기를 동적으로 결정하고 InfoBox의 높이와 너비를 올바르게 설정하는 것이 었습니다. 이 문제는 콘텐츠가 DOM에 삽입되기 전에 차원 값이 올바르지 않습니다. 결과적으로 나의 접근 방식은 다음이었다

  1. 삽입 할 필요가있는 DOM 내용 요소를 작성
  2. 는 임시 컨테이너에 삽입을
  3. 받기 임시 컨테이너의 크기
  4. 제거 임시 컨테이너
  5. 삽입 인포 박스의 내용 및 여기서

함께 수행 예는 임시 용기 크기에 기초하여 높이 및 넓이를 설정 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); 

희망이 있습니다.

0

당신이 (가) 인포 박스 무승부 방법을 무시하고 인포 박스의 위치를 ​​변경 할 수 있습니다 그것은 렌더링 된 후 :

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