Custom MapType & Projection in Google Map API v3
Сегодня я бы хотел продолжить начатый ранее разговор о гуглокартах. Сегодня будет сложный урок с большой долей теории и не смотря на выпитые два литра пива я все равно намереваюсь это сделать.
На самом деле я искал репродукцию Моны Лизы для того чтобы нарисовать мишень (десяточку) на ее улыбке, но в галереи этой репродукции не было. Да и вообще к тому времени как я при помощи своего гуглоридера (сколько раз мама говорила - ставь звездочки) нашел эту галерею, я уже об этом не думал. Кстати о галерее - The Kremer Collection! Очень уж она хороша, в плане того, что ребята не заебались и отсканили какие-то каляки-маляки. Но видимо в силу своей неграмотности, убогости и непросвещенности я ни одной знакомой фамилии художника так и не заметил.
Upadte 17.08.10 ShadowX уже уличил меня в том, что я незаметил Рембранта.
Так, хватит болтать не по теме. С десяточкой не вышло, а вот галерея как мне показалось работает не по феншую. Мало того что работает на выходных и без обеденного перерыва так еще и на Google Map API v2. Простите за ключевики но такова природа блога что его должны находить через поисковик. И задумал я коварное, а точнее перевести ее на Google Map API v3. И вооружился для этого мануалом, но тот не помог мне, потому что глуп я и в системах координат, да и вообще в математике не шарю. И стал я читать умную литературу... вру! Кароче, нагуглил я реализацию трех систем координат (про две из них я уже писал) Меркатора, Гэлла и Питерса и та что мне была нужна - Эвклидова
Вот с ней то я дальше и игрался, переписав код как мне больше нравилось и применив функцию создания имени картинки, честно стыренную из галереи, я сообразил вот это:
// Эвклидова Проекция
var EuclideanProjection = function (){
// Ширина, она же высота одного кусочка картинки
var EUCLIDEAN_RANGE = 256;
// Центр этой самой картинки
this.pixelOrigin = new google.maps.Point(EUCLIDEAN_RANGE / 2, EUCLIDEAN_RANGE / 2);
// Количество градусов в одном пикселе картинки
this.pixelsPerLonDegree = EUCLIDEAN_RANGE / 360;
// Количество радиан в одном пикселе картинки
this.pixelsPerLonRadian = EUCLIDEAN_RANGE / (2 * Math.PI);
};
// Эти два метода надо реализовать в классе проекции
// http://code.google.com/apis/maps/documentation/javascript/maptypes.html#Projections
EuclideanProjection.prototype = {
pixelOrigin : new google.maps.Point(0,0),
pixelsPerLonDegree : 0,
pixelsPerLonRadian : 0,
// код взят из
// http://library.ucf.edu/Web/JS/Maps.js
// в работе можно глянуть тут
// http://library.ucf.edu/Administration/Maps/
// страна должна знать героев в лицо
fromLatLngToPoint : function(latLng, opt_point) {
var point = opt_point || new google.maps.Point(0, 0);
point.x = this.pixelOrigin.x + latLng.lng() * this.pixelsPerLonDegree;
point.y = this.pixelOrigin.y + (-1 * latLng.lat()) * this.pixelsPerLonDegree;
//console.log("fromLatLngToPoint", latLng, point);
return point;
},
fromPointToLatLng : function(point) {
var lng = (point.x - this.pixelOrigin.x) / this.pixelsPerLonDegree,
lat = -1 * (point.y - this.pixelOrigin.y) / this.pixelsPerLonDegree;
//console.log("fromPointToLatLng", point, new google.maps.LatLng(lat , lng, true));
return new google.maps.LatLng(lat , lng, true);
}
};
// Новый тип карты CoordMapType
// http://code.google.com/apis/maps/documentation/javascript/maptypes.html#MapTypeInterface
var CoordMapType = function (){};
CoordMapType.prototype = {
name : "Custom Map Type",
alt : "Tile Coordinate Map Type",
minZoom : 0,
maxZoom : 5,
tileSize : new google.maps.Size(256,256),
projection : new EuclideanProjection(),
// Эта функция взята из галереи The Kremer Collection
// http://www.thekremercollection.com/art/artists/Adriaen-Thomasz-Key-%28formerly-attributed-to%29/Portrait-of-a-Spanish-grande/detail/
// и испотльзуеться только для составления имен картинок эток конкретной галереи
getTile : function(coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('DIV'),
c = 1 << zoom,
x = coord.x,
y = coord.y;
if (y < 0 || y >= c || x < 0 || x >= c || zoom > 4) {
div.style.height = '256px';
div.style.width = '256px';
div.style.backgroundColor = '#fcf8ed';
div.style.fontSize = '9';
div.style.textAlign = 'center';
div.innerHTML = zoom > 4 ? 'Sorry, we have no map <br /> images for this zoom level.' : '';
return div;
}
for (var g = 0, f = "t"; g < zoom; g++) {
c = c / 2;
if (y < c) {
if (x < c) {
f += "q"
} else {
f += "r";
x -= c
}
} else {
if (x < c) {
f += "t";
y -= c
} else {
f += "s";
x -= c;
y -= c
}
}
}
div.innerHTML = "<img src=\"http://www.thekremercollection.com/art/img/paintings/zoom/portrait_of_a_spanish_grande_tiles_14/" + f + ".jpg\" alt=\"\" width=\"256\" height=\"256\" />";
return div;
}
};
function initialize() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 0,
center: new google.maps.LatLng(0,0),
mapTypeControlOptions: {
mapTypeIds: ['myCustomMap']
}
});
map.mapTypes.set('myCustomMap', new CoordMapType());
map.setMapTypeId('myCustomMap');
}
google.maps.event.addDomListener(window, 'load', initialize);
Ну и конечно можете пощупать в живую
PS Совсем забыл сказать что последний уровень увеличения не работает умышленно, хотел показать как сделать обработку несуществующих данных.
Свежие комментарии