我正在尝试将Pamela Fox的“智能信息窗口”代码实施到我的Google地图中,而我似乎无法将其运行起来。将显示地图,并在其上正确放置标记。但是当我点击标记时没有任何反应,但我没有收到任何错误消息,我必须承认有点迷失。
我哪里错了?
HTML表单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>All Locations</title>
<link rel="stylesheet" href="css/alllocationsstyle.css" type="text/css" media="all" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&language=en"></script>
<script type="text/javascript" src="js/smartinfowindow.js"></script>
<script type="text/javascript">
var customIcons = {
0: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
},
1: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_green.png',
shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
}
};
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(54.312195845815246,-4.45948481875007),
zoom:6,
mapTypeId: 'roadmap'
});
downloadUrl("phpfile.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
var locationname = markers[i].getAttribute("locationname");
var address = markers[i].getAttribute("address");
var totalfinds = markers[i].getAttribute("totalfinds");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("osgb36lat")),
parseFloat(markers[i].getAttribute("osgb36lon")));
var html = locationname + "<p>" + 'No. of finds: ' + "<b>" + totalfinds + "</b>" + "</p>";
var icon = {};
if (totalfinds == 0) {
icon = customIcons[0];
} else if (totalfinds >= 1) {
icon = customIcons[1];
}
var marker = new google.maps.Marker({
map: map,
position: point,
title: address,
icon: icon.icon,
shadow: icon.shadow
});
bounds.extend(point);
map.fitBounds(bounds);
google.maps.event.addListener(point, 'click', function(e) {
var infobox = new SmartInfoWindow({position: point, map: map, html: html});
});
}
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
</script>
</head>
<body onLoad="load()">
<div id="map"></div>
</body>
</html>
Smart Window JS
/* An SmartInfoWindow is like an info window, but it displays
* under the marker, opens quicker, and has flexible styling.
* @param {Object} opts Passes configuration options.
*/
function SmartInfoWindow(opts) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.position;
this.content_ = opts.content;
this.map_ = opts.map;
this.height_ = 351;
this.width_ = 280;
this.size_ = new google.maps.Size(this.height_, this.width_);
this.offsetVertical_ = -this.height_;
this.offsetHorizontal_ = 0;
this.panned_ = false;
this.setMap(this.map_);
// We need to listen to bounds_changed event so that we can redraw
// absolute position every time the map moves.
// This is only needed because we append to body instead of map panes.
var me = this;
google.maps.event.addListener(this.map_, 'bounds_changed', function() {
me.draw();
});
}
/**
* SmartInfoWindow extends GOverlay class from the Google Maps API
*/
SmartInfoWindow.prototype = new google.maps.OverlayView();
/**
* Creates the DIV representing this SmartInfoWindow
*/
SmartInfoWindow.prototype.onRemove = function() {
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
/**
* Called when the overlay is first added to the map.
*/
SmartInfoWindow.prototype.onAdd = function() {
// Creates the element if it doesn't exist already.
this.createElement();
};
/**
* Redraw based on the current projection and zoom level.
*/
SmartInfoWindow.prototype.draw = function() {
// Since we use bounds changed listener, projection is sometimes null
if (!this.getProjection()) {
return;
}
// This gives us the position in the tiles div.
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
var centerPosition = this.getProjection().fromLatLngToDivPixel(this.map_.getCenter());
var centerPositionReal = new google.maps.Point(this.map_.getDiv().offsetWidth/2, this.map_.getDiv().offsetHeight/2);
// Figure out difference between map div and tiles div, so that we can
// calculate position in map div
var centerOffsetX = -centerPosition.x + centerPositionReal.x;
var centerOffsetY = -centerPosition.y + centerPositionReal.y;
if (!pixPosition) return;
var alignment = this.getBestAlignment();
var paddingTop = 0;
var paddingLeft = 0;
var widthLess = 0;
switch (alignment) {
case SmartInfoWindow.Align.ABOVE:
this.width_ = 280;
this.height_ = 351;
image = 'infobox_above.gif';
this.offsetX_ = -(this.width_ / 2 - 17);
this.offsetY_ = -(this.height_ + 12);
break;
case SmartInfoWindow.Align.BELOW:
this.width_ = 280;
this.height_ = 351;
image = 'infobox_below.gif';
this.offsetX_ = -(this.width_ / 2 - 17);
this.offsetY_ = -15;
paddingTop = 20;
break;
case SmartInfoWindow.Align.LEFT:
this.width_ = 307;
this.height_ = 326;
image = 'infobox_left.gif';
this.offsetX_ = -(this.width_) + 10;
this.offsetY_ = -(this.height_ / 2 + 33);
widthLess = 20;
break;
case SmartInfoWindow.Align.RIGHT:
image = 'infobox_right.gif';
this.width_ = 307;
this.height_ = 326;
this.offsetX_ = 6;
this.offsetY_ = -(this.height_ / 2 + 33);
paddingLeft = 20;
widthLess = 20;
break;
}
// 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.offsetX_) + centerOffsetX + 'px';
this.div_.style.height = this.height_ + 'px';
this.div_.style.top = (pixPosition.y + this.offsetY_) + centerOffsetY + 'px';
//this.div_.style.paddingTop = paddingTop + 'px';
//this.div_.style.paddingLeft = paddingLeft + 'px';
this.div_.style.background = 'url("images/' + image + '")';
this.div_.style.display = 'block';
this.wrapperDiv_.style.width = (this.width_- widthLess) + 'px';
this.wrapperDiv_.style.height = this.height_ + 'px';
this.wrapperDiv_.style.marginTop = paddingTop + 'px';
this.wrapperDiv_.style.marginLeft = paddingLeft + 'px';
this.wrapperDiv_.style.overflow = 'hidden';
if (!this.panned_) {
this.panned_ = true;
this.maybePanMap();
}
};
/**
* Creates the DIV representing this SmartInfoWindow 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.
*/
SmartInfoWindow.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.style.border = '0px none';
div.style.position = 'absolute';
div.style.overflow = 'hidden';
var wrapperDiv = this.wrapperDiv_ = document.createElement('div');
var contentDiv = document.createElement('div');
if (typeof this.content_ == 'string') {
contentDiv.innerHTML = this.content_;
} else {
contentDiv.appendChild(this.content_);
}
var topDiv = document.createElement('div');
topDiv.style.textAlign = 'right';
var closeImg = document.createElement('img');
closeImg.src = 'images/closebigger.gif';
closeImg.style.width = '32px';
closeImg.style.height = '32px';
closeImg.style.cursor = 'pointer';
topDiv.appendChild(closeImg);
function removeSmartInfoWindow(ib) {
return function() {
ib.setMap(null);
};
}
google.maps.event.addDomListener(closeImg, 'click', removeSmartInfoWindow(this));
wrapperDiv.appendChild(topDiv);
wrapperDiv.appendChild(contentDiv);
div.appendChild(wrapperDiv);
div.style.display = 'none';
// Append to body, to avoid bug with Webkit browsers
// attempting CSS transforms on IFRAME or SWF objects
// and rendering badly.
document.body.appendChild(div);
} 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.
}
};
SmartInfoWindow.mouseFilter = function(e) {
e.returnValue = 'true';
e['handled'] = true;
}
/**
* Closes infowindow
*/
SmartInfoWindow.prototype.close = function() {
this.setMap(null);
};
/**
* Pan the map to fit the SmartInfoWindow,
* if its top or bottom corners aren't visible.
*/
SmartInfoWindow.prototype.maybePanMap = function() {
// if we go beyond map, pan map
var map = this.map_;
var projection = this.getProjection();
var bounds = map.getBounds();
if (!bounds) return;
// The dimension of the infowindow
var iwWidth = this.width_;
var iwHeight = this.height_;
// The offset position of the infowindow
var iwOffsetX = this.offsetX_;
var iwOffsetY = this.offsetY_;
var anchorPixel = projection.fromLatLngToDivPixel(this.latlng_);
var bl = new google.maps.Point(anchorPixel.x + iwOffsetX + 20,
anchorPixel.y + iwOffsetY + iwHeight);
var tr = new google.maps.Point(anchorPixel.x + iwOffsetX + iwWidth,
anchorPixel.y + iwOffsetY);
var sw = projection.fromDivPixelToLatLng(bl);
var ne = projection.fromDivPixelToLatLng(tr);
// The bounds of the infowindow
if (!map.getBounds().contains(ne) || !map.getBounds().contains(sw)) {
map.panToBounds(new google.maps.LatLngBounds(sw, ne));
}
};
/**
* @enum {number}
*/
SmartInfoWindow.Align = {
ABOVE: 0,
LEFT: 1,
RIGHT: 2,
BELOW: 3
};
/**
* Finds best alignment for infowindow.
* @return {number} Alignment.
*/
SmartInfoWindow.prototype.getBestAlignment = function() {
var bestAlignment = SmartInfoWindow.Align.LEFT;
var minPan = 0;
for (var alignment in SmartInfoWindow.Align) {
var alignment = SmartInfoWindow.Align[alignment];
var panValue = this.getPanValue(alignment);
if (panValue > minPan) {
minPan = panValue;
bestAlignment = alignment;
}
}
return bestAlignment;
};
/**
* Calculates distance of corner for each alignment.
* @param {number} alignment An alignment constant.
* @return {number} Distance for that alignment.
*/
SmartInfoWindow.prototype.getPanValue = function(alignment) {
var mapSize = new google.maps.Size(this.map_.getDiv().offsetWidth,
this.map_.getDiv().offsetHeight);
var bounds = this.map_.getBounds();
var sideLatLng;
switch (alignment) {
case SmartInfoWindow.Align.ABOVE:
sideLatLng = new google.maps.LatLng(bounds.getNorthEast().lat(),
this.latlng_.lng());
break;
case SmartInfoWindow.Align.BELOW:
sideLatLng = new google.maps.LatLng(bounds.getSouthWest().lat(),
this.latlng_.lng());
break;
case SmartInfoWindow.Align.RIGHT:
sideLatLng = new google.maps.LatLng(this.latlng_.lat(),
bounds.getNorthEast().lng());
break;
case SmartInfoWindow.Align.LEFT:
sideLatLng = new google.maps.LatLng(this.latlng_.lat(),
bounds.getSouthWest().lng());
break;
}
var dist = SmartInfoWindow.distHaversine(this.latlng_.lat(), this.latlng_.lng(),
sideLatLng.lat(), sideLatLng.lng());
return dist;
};
/**
* Converts degrees to radians.
* @param {number} num Angle in degrees.
* @return {number} Angle in radians.
*/
SmartInfoWindow.toRad = function(num) {
return num * Math.PI / 180;
}
/**
* Calculates distance between two coordinates.
* @param {number} lat1 Latitude of first coord.
* @param {number} lon1 Longitude of second coord.
* @param {number} lat2 Latitude of second coord.
* @param {number} lon2 Longitude of second coord.
* @return {number} The distance.
*/
SmartInfoWindow.distHaversine = function(lat1, lon1, lat2, lon2) {
var R = 6371; // earth's mean radius in km
var dLat = SmartInfoWindow.toRad(lat2 - lat1);
var dLon = SmartInfoWindow.toRad(lon2 - lon1);
lat1 = SmartInfoWindow.toRad(lat1), lat2 = SmartInfoWindow.toRad(lat2);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1) * Math.cos(lat2) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
}
更新代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Locations</title>
<link rel="stylesheet" href="css/alllocationsstyle.css" type="text/css" media="all" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&language=en"></script>
<script type="text/javascript">
function InfoBox(opts) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.offsetVertical_ = -195;
this.offsetHorizontal_ = 0;
this.height_ = 165;
this.width_ = 266;
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.style.border = "0px none";
div.style.position = "absolute";
div.style.background = "url('http://gmaps-samples.googlecode.com/svn/trunk/images/blueinfowindow.gif')";
div.style.width = this.width_ + "px";
div.style.height = this.height_ + "px";
var contentDiv = document.createElement("div");
contentDiv.style.padding = "30px"
contentDiv.innerHTML = "<b>Hello World!</b>";
var topDiv = document.createElement("div");
topDiv.style.textAlign = "right";
var closeImg = document.createElement("img");
closeImg.style.width = "32px";
closeImg.style.height = "32px";
closeImg.style.cursor = "pointer";
closeImg.src = "http://gmaps-samples.googlecode.com/svn/trunk/images/closebigger.gif";
topDiv.appendChild(closeImg);
function removeInfoBox(ib) {
return function() {
ib.setMap(null);
};
}
google.maps.event.addDomListener(closeImg, 'click', removeInfoBox(this));
div.appendChild(topDiv);
div.appendChild(contentDiv);
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;
};
</script>
<script type="text/javascript">
var customIcons = {
0: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
},
1: {
icon: 'http://labs.google.com/ridefinder/images/mm_20_green.png',
shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
}
};
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(54.312195845815246,-4.45948481875007),
zoom:6,
mapTypeId: 'roadmap'
});
// Change this depending on the name of your PHP file
downloadUrl("phpfile.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
var locationname = markers[i].getAttribute("locationname");
var address = markers[i].getAttribute("address");
var totalfinds = markers[i].getAttribute("totalfinds");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("osgb36lat")),
parseFloat(markers[i].getAttribute("osgb36lon")));
var html = locationname + "<p>" + 'No. of finds: ' + "<b>" + totalfinds + "</b>" + "</p>";
var icon = {};
if (totalfinds == 0) {
icon = customIcons[0];
} else if (totalfinds >= 1) {
icon = customIcons[1];
}
var marker = new google.maps.Marker({
map: map,
position: point,
title: address,
icon: icon.icon,
shadow: icon.shadow
});
google.maps.event.addListener(marker, "click", function(e) {
var infoBox = new InfoBox({latlng: marker.getPosition(), map: map});
});
bounds.extend(point);
map.fitBounds(bounds);
}
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
</script>
</head>
<body onLoad="load()">
<div id="map"></div>
</body>
</html>
答案 0 :(得分:1)
如果我正确地阅读您的代码,您可以将侦听器分配给指向(google.maps.LatLng),而您应该为标记执行此操作。在片段中:
google.maps.event.addListener(point, 'click', function(e) {
var infobox = new SmartInfoWindow({position: point, map: map, html: html});
});
将点更改为标记:
google.maps.event.addListener(marker, 'click', function(e) {
var infobox = new SmartInfoWindow({position: point, map: map, html: html});
});