
Покуда метры направления растеризует маркеры в картинки, строят супер системы группировок и кластеризаций и дрожат над каждым лишним килобайтом в скриптах, давайте я расскажу самый простой, стабильны, и банальный способ сделать жизнь свою, своих пользователей, своих карт и своего сервера чуть прекрасней.
Как будет сказано чуть позже покорение карт состоит из 5ти шагов.
Первый из них это загрузка карты( не все так просто как думается ), а вот второй — это загрузка на эти самые карты данных.
Он то нам и интересен.
В настоящий момент распространены два подхода к загрузке данный маркеров на карту.
1. Грузим все данные через ajax, либо сразу их javascript
2. Дергаем сервер на предмет «а какие объекты у нас в текущем viewport?»
Первый вариант имеет право на жизнь, особенно если маркеров мало, да и markermanager тут помогает(скрывать невидимые), а вот второй давайте забудем как страшный сон.
Итак, будем считать
что у нас есть функция для загрузке данных по координатному боксу
- $.get("ajax/load-map-data?SE="+MySECorner.toString()+"&NE="+MyNECorner.toString()+"&zoom="+currentZoom,
- function(data){
- //wow! i got the data for map!
- //for whole visible viewport( and just for it)
- });
* This source code was highlighted with Source Code Highlighter.
Используя ее мы убиваем свой сервер невозможностью кеширования, а пользователя задержками при малейшем сдвиге карты( фи 4 aroundme номер раз ).
Как же этот хренов гугл работает так быстро!
Он вроде бы загружает картинки своих карт… мелкими кусочками, 256х256 пикселей.
Подумай %username%, почему бы не сделать тоже самое?
Если бы мы грузили свои данные таким образом то:
- можно было бы просто обкешироваться на сервере
- перемещение карты меньше чем на 256 пикселей, скорее всего, не приводил бы к подгрузке новых блоков данных
- А так как нормальный браузер поддерживает 4-6 параллельных запросов к одному серверу( или даже больше, use jsonp luke! на пару субдоменов ), то и тоже самое количество данных мы получали бы в пару потоков и, в итоге, малек быстрее
Лично себя я отношу к категории извращенцев, и моя реализация таких вот хитрых запросов, плюс marker manager & clustering занимает порядка 6000 строк.
Не буду вас сейчас мучать тем о чем расскажу в последующих статьях.
А просто расскажу
Как сделать это просто
Реализация представлена для google maps v3, она при желании за секунды переделывается под yandex карты( берем тайлы под гугл и отображаем их на яндекс картах, либо реализуем описанный интерфейс изначально на яндекс ITile и используем их ковертер), либо, чуть поработав напильником, под google maps v2
В любом случае есть замечательный SparseTileLayer разобрав который можно отвязаться как от апи карт, так и от всего остального( и который мы сейчас используем, так как на момент окончания разработки карт пользовательских вариантов в v3 не было)
Итак создадим свой тип карты
- function ServerFetchMapType() {
- }
-
- ServerFetchMapType.prototype.tileSize = new google.maps.Size(256,256);
- ServerFetchMapType.prototype.maxZoom = 32;
- ServerFetchMapType.prototype.name = "Server Tile #s";
- ServerFetchMapType.prototype.alt = "Server Data Tile Map Type";
-
-
- ServerFetchMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
- var addr=this.getAddr(coord,zoom);
- //test - may be we allready load this block?
- if(ServerFetchedTiles[addr]){
- return
- }
-
- $.get("ajax/load-map-tile?"+addr,
- function(data){
- ServerFetchedTiles[addr]=data;
- //wow! i got the data just for this tile
- });
-
- };
-
-
- //and add this tile overlay to current map type
- map.overlayMapTypes.insertAt(0, new ServerFetchMapType() );
* This source code was highlighted with Source Code Highlighter.
Как не странно — это все :)
Мы создали свой тип карты, только заместо картинок выполняем запросы к серверу.
А запросы бывают двух вариантов — гугла подобные, когда мы адресуем тайл по его x,y,z либо стандартные, по баундинг боксу.
Реализация данных методов:
- //we can request tile as tile(x,y,z)
- ServerFetchMapType.prototype.getAddrXY = function(coord, zoom){
- return "x="+coord.x+"&y="+coor.y+"&z="+zoom;
- }
-
- //or as latlng box
- ServerFetchMapType.prototype.getAddrLatLng = function(coord, zoom){
-
- //helper function for mercator projection
- var mercator = function(point){
- //
- var numtiles=Math.pow(2,point.zoom);
- var bitmapsize=numtiles*256;
- var bitmaporigo =bitmapsize/2;
- var pixelsperlondegree=bitmapsize/360;
- var pixelsperlonradian=bitmapsize/(2*Math.PI);
-
- var lat=bitmaporigo+(pixelsperlondegree*point.x);
- var ged2rad=((point.t*Math.PI)/180.0);
- var sn=Math.sin(deg2rad);
- var lng=((bitmaporigo - 0.5 * log((1+sn)/(1-sn)) * pixelsperlonradian));
- return new google.maps.LatLng(lat,lng);
- }
- var point1={x:coord.x*256,y:coord.y*256,z:zoom} ;
- var point2={x:(coord.x+1)*256,y:(coord.y+1)*256,z:zoom} ;
- var ne=mercator(point1);
- var sw=mercator(point2);
- return "NE="+ne.toString()+"&SW="+sw.toString()+"&z="+zoom;
- }
* This source code was highlighted with Source Code Highlighter.
* в данном случаем мы очень не красиво реализовали свою функцию меркатора, намного лучше использотьвать встроеные конвертеры(yandex.converter) и проекторы(overlay.projection) АПИ карт.
Что остается
Остается ответить на вопрос — что будет если у вас нету данные для загружаемых тайлов( вы находитесь посреди уральских гор ) и зачем вам в этом случае вообще грузить данные.
Ответ на этот вопрос я давал еще полтора года назад.
Чтож под конец сравним как работает подгрузка данных на wikimapia, esosedi, gdeetotdom и (стыд и позор програмистам!) aroundme
кстати следует уточнить что три указаных «умных» сайта используют кодировку «z-тайлов», по сути путь в quadtree, но викимапия, через свой апи, позволяет запрашивать данные в x-z-y адресации.
Вот и все
Я надеюсь что мои мысли дойдут до людей в этих мыслях нуждающихся, если будут вопросы — спрашивайте.
Если будут просто вопросы по картографии — тоже спрашивайте, раз уж мне пришлось начать свой блог( зеркало blogspot) на своем корявом английском, всегда буду рад написать о проблемах волнующих массы.
Что ж, пойду я дописывать вторую статью в которой расскажу много новых секретов, ранее на хабре не озвученных. А Вы запасайтесь кофем и болтайте