在下面的工作示例中,我实现了一个自定义 MapType。该示例是基本地图类型示例的混搭,它展示了如何使用 getTile() 创建自定义地图图块,以及自定义投影示例,这样我就不必担心自己在图块坐标和地理坐标之间进行转换。
在这个简单的测试中,我只是为每个图块添加了一个自定义标记。但是,releaseTile() 中的瓦片清理速度很慢。为什么它很慢,有没有更好的方法在自定义地图图块中创建可点击对象?
<!DOCTYPE html>
<html>
<head>
<title>Basic map types</title>
<link href="default.css" rel="stylesheet">
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
/** @constructor */
function CoordMapType() {
}
var map;
var TILE_SIZE = 256;
var chicago = new google.maps.LatLng(41.850033,-87.6500523);
CoordMapType.prototype.tileSize = new google.maps.Size(TILE_SIZE,TILE_SIZE);
CoordMapType.prototype.maxZoom = 19;
var projection = new MercatorProjection();
createCustomMarker = function(tile_coord, zoom) {
// put the position in the center of the tile
var num_tiles = 1 << zoom;
var pixel_coord = new google.maps.Point(
(tile_coord.x + .5) * TILE_SIZE,
(tile_coord.y + .5) * TILE_SIZE
);
var world_coord = new google.maps.Point(
pixel_coord.x / num_tiles,
pixel_coord.y / num_tiles
);
var custom_position = projection.fromPointToLatLng(world_coord);
var contentString = '<div id="content">'+
'<h1 id="firstHeading" class="firstHeading">A Heading</h1>'+
'<div id="bodyContent">'+
'<p>' +
'tile: ' + tile_coord.x + ', ' + tile_coord.y + '<br>' +
'zoom:' + zoom;
'</p>' +
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: custom_position,
map: map,
title: 'custom_marker',
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 4,
strokeColor: '#1122FF',
fillColor: '#1122FF'
}
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
return marker;
}
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
div.custom_markers = [];
div.custom_markers.push(createCustomMarker(coord, zoom));
return div;
};
CoordMapType.prototype.releaseTile = function(tile) {
var length = tile.custom_markers.length;
var custom_marker = null;
for (var i = 0; i < length; i++) {
// clean up the markers in this tile
custom_marker = tile.custom_markers[i];
google.maps.event.clearListeners(custom_marker);
custom_marker.setMap(null);
custom_marker = null;
}
};
CoordMapType.prototype.name = 'Tile #s';
CoordMapType.prototype.alt = 'Tile Coordinate Map Type';
var coordinateMapType = new CoordMapType();
function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}
function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}
function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}
/** @constructor */
function MercatorProjection() {
this.pixelOrigin_ = new google.maps.Point(TILE_SIZE / 2,
TILE_SIZE / 2);
this.pixelsPerLonDegree_ = TILE_SIZE / 360;
this.pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}
MercatorProjection.prototype.fromLatLngToPoint = function(latLng,
opt_point) {
var me = this;
var point = opt_point || new google.maps.Point(0, 0);
var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999,
0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
-me.pixelsPerLonRadian_;
return point;
};
MercatorProjection.prototype.fromPointToLatLng = function(point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -
Math.PI / 2);
return new google.maps.LatLng(lat, lng);
};
function initialize() {
var mapOptions = {
zoom: 10,
center: chicago,
streetViewControl: false,
mapTypeId: 'coordinate',
mapTypeControlOptions: {
mapTypeIds: ['coordinate'],
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
google.maps.event.addListener(map, 'maptypeid_changed', function() {
var showStreetViewControl = map.getMapTypeId() != 'coordinate';
map.setOptions({'streetViewControl': showStreetViewControl});
});
// Now attach the coordinate map type to the map's registry
map.mapTypes.set('coordinate', coordinateMapType);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>