Главная > JavaScript, Программирование > Custom MapType & Projection in Google Map API v3

Custom MapType & Projection in Google Map API v3

16 Август 2010

Сегодня я бы хотел продолжить начатый ранее разговор о гуглокартах. Сегодня будет сложный урок с большой долей теории и не смотря на выпитые два литра пива я все равно намереваюсь это сделать.

На самом деле я искал репродукцию Моны Лизы для того чтобы нарисовать мишень (десяточку) на ее улыбке, но в галереи этой репродукции не было. Да и вообще к тому времени как я при помощи своего гуглоридера (сколько раз мама говорила - ставь звездочки) нашел эту галерею, я уже об этом не думал. Кстати о галерее - 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 Совсем забыл сказать что последний уровень увеличения не работает умышленно, хотел показать как сделать обработку несуществующих данных.

  1. 17 Август 2010 в 04:32 | #1
    Что-то с хостингом нездоровое - эта и предыдущая заметки читались в ридере, но при попытке открыть сайт - фигушки! Не открывается сайт минут по 10-15 (
  2. 17 Август 2010 в 08:54 | #2
    Крутая тема, возьму на заметку! Год назад думал делать для карт какой-то свой человекопонятный апи, для одного прожекта, всё сделал без апи, для начала, на костылях - а его не стартанули из-за нехватки материала, обидно, забил... Сча вроде уже собрали процентов 50% материала, думаю таки запущу... Гугл всё-таки мощная штука, но АПИ у их многих продуктов довольно кривые, особенно в календаре
  3. 17 Август 2010 в 10:36 | #3
    @kikaha Незнаю ничего такого. у меня все отлично работает из офиса и дома. @deerua Ага тема то что надо. думаю отвлечся не надолго на новый JUI и таки сделать десяточку на этом чуваке. Тебе желаю удачи с проектом, бери меня в долю ;) И про гугловое АПИ ты верно сказал местами очень кривое. Вот мне например запомнился Friend Connect
Комментирование отключено.