Несмотря на все мои попытки к исправление ситуации с технологиями загрузки данных на карту, люди все продолжают и продолжают работать по старинке, загружая либо все данные вьюпорта при малейшем движении карты, либо просто загружая все данные вообще.
Покуда метры направления растеризует маркеры в картинки, строят супер системы группировок и кластеризаций и дрожат над каждым лишним килобайтом в скриптах, давайте я расскажу самый простой, стабильны, и банальный способ сделать жизнь свою, своих пользователей, своих карт и своего сервера чуть прекрасней.
Как будет сказано чуть позже покорение карт состоит из 5ти шагов.
Первый из них это загрузка карты( не все так просто как думается ), а вот второй — это загрузка на эти самые карты данных.
Он то нам и интересен.
В настоящий момент распространены два подхода к загрузке данный маркеров на карту.
1. Грузим все данные через ajax, либо сразу их javascript
2. Дергаем сервер на предмет «а какие объекты у нас в текущем viewport?»
Первый вариант имеет право на жизнь, особенно если маркеров мало, да и markermanager тут помогает(скрывать невидимые), а вот второй давайте забудем как страшный сон.
Используя ее мы убиваем свой сервер невозможностью кеширования, а пользователя задержками при малейшем сдвиге карты( фи 4 aroundme номер раз ).
Как же этот хренов гугл работает так быстро!
Он вроде бы загружает картинки своих карт… мелкими кусочками, 256х256 пикселей.
Если бы мы грузили свои данные таким образом то:
Лично себя я отношу к категории извращенцев, и моя реализация таких вот хитрых запросов, плюс marker manager & clustering занимает порядка 6000 строк.
Не буду вас сейчас мучать тем о чем расскажу в последующих статьях.
А просто расскажу
Реализация представлена для google maps v3, она при желании за секунды переделывается под yandex карты( берем тайлы под гугл и отображаем их на яндекс картах, либо реализуем описанный интерфейс изначально на яндекс ITile и используем их ковертер), либо, чуть поработав напильником, под google maps v2
В любом случае есть замечательный SparseTileLayer разобрав который можно отвязаться как от апи карт, так и от всего остального( и который мы сейчас используем, так как на момент окончания разработки карт пользовательских вариантов в v3 не было)
Итак создадим свой тип карты
Как не странно — это все :)
Мы создали свой тип карты, только заместо картинок выполняем запросы к серверу.
А запросы бывают двух вариантов — гугла подобные, когда мы адресуем тайл по его x,y,z либо стандартные, по баундинг боксу.
Реализация данных методов:
* в данном случаем мы очень не красиво реализовали свою функцию меркатора, намного лучше использотьвать встроеные конвертеры(yandex.converter) и проекторы(overlay.projection) АПИ карт.
Остается ответить на вопрос — что будет если у вас нету данные для загружаемых тайлов( вы находитесь посреди уральских гор ) и зачем вам в этом случае вообще грузить данные.
Ответ на этот вопрос я давал еще полтора года назад.
Чтож под конец сравним как работает подгрузка данных на wikimapia, esosedi, gdeetotdom и (стыд и позор програмистам!) aroundme
кстати следует уточнить что три указаных «умных» сайта используют кодировку «z-тайлов», по сути путь в quadtree, но викимапия, через свой апи, позволяет запрашивать данные в x-z-y адресации.
Я надеюсь что мои мысли дойдут до людей в этих мыслях нуждающихся, если будут вопросы — спрашивайте.
Если будут просто вопросы по картографии — тоже спрашивайте, раз уж мне пришлось начать свой блог( зеркало blogspot) на своем корявом английском, всегда буду рад написать о проблемах волнующих массы.
Что ж, пойду я дописывать вторую статью в которой расскажу много новых секретов, ранее на хабре не озвученных. А Вы запасайтесь кофем и болтайте
Покуда метры направления растеризует маркеры в картинки, строят супер системы группировок и кластеризаций и дрожат над каждым лишним килобайтом в скриптах, давайте я расскажу самый простой, стабильны, и банальный способ сделать жизнь свою, своих пользователей, своих карт и своего сервера чуть прекрасней.
Как будет сказано чуть позже покорение карт состоит из 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) на своем корявом английском, всегда буду рад написать о проблемах волнующих массы.
Что ж, пойду я дописывать вторую статью в которой расскажу много новых секретов, ранее на хабре не озвученных. А Вы запасайтесь кофем и болтайте