Клуб API Карт

Центрирование

Пост в архиве.
sve4458
7 декабря 2010, 18:57

Доброго времени суток.

Возник такой вопрос. В примерах, которые приводятся в ответах часто центрирование карты приводится в самом начале. Но как быть, если я заранее не знаю куда центрировать? Я использую пример http://api.yandex.ru/maps/jsapi/examples/multiplygeocoding.html. Здесь за центрирование отвечает map.setCenter(new YMaps.GeoPoint(37.64, 55.76), 4);

Вопрос собственно в том, как сделать так, чтобы отцентрировать можно было после получения всех найденных объектов (в приведенном примере после вызова функции MultiplyGeocoder(data);)?

15 комментариев
создайте экземпляр класса GeoCollectionBounds и добавляейте в него все найденные геоточки из выдачи геокодера.
А потом спозиционируйте карту на этот экземпляр методом setBounds
Да, я пробовал так сделать. 

|            // Координаты или адреса географических объектов
|            var data = [...];
|
|            bounds = new YMaps.GeoCollectionBounds();
|
|            var geocoder = new MultiplyGeocoder(data);
|            map.addOverlay(geocoder);
|
|            map.setBounds(bounds);

...

|    if (geocoder.length()) {
|    var placemark = new YMaps.Placemark(new YMaps.GeoPoint(geocoder.get(0).getGeoPoint().getX(),geocoder.get(0).getGeoPoint().getY()), {style: ""default#hospitalIcon""});
| placemark.description = request[1];
| _this.add(placemark);
| bounds.add(geocoder.get(0).getGeoPoint());

|    }


После выполнения карта центрируется возле Африки. Насколько я понимаю, проблема с видимостью переменной bounds. А может и в чем-то другом. Подскажите пожалуйста
по коду это вообще совсем не ясно, но я бы

map.addOverlay(geocoder);
map.setBounds(bounds);


перенес бы в низ, где вроде обработка ответа геокодера.
В том месте где они сейчас нарисованы - они еще пусты.
Они должны быть наверху. Приведу весь код:

 

Яндексe>


 





повторю свои слова :)
даже если "они" должны быть выше - они там не отработают.
В вашем, сложном если честно, случае все крайне плохо.
Вы должны дождаться успешной отработки ВСЕХ геокодеров, и только после этого эти самые "они" должны отработать, добавившись на карту.

А у вас сначала на карту добаляется пустой еще collection, потом пустой еще bounds, и через несколько мгновений этот bounds начинает собираться..

Вариант номер 2, попроще будет, и кстати покрасивше
ровно в конце YMaps.Events.observe(geocoder,
тоесть когда вы забили очередную часть координат в bounds - центрируйте карту на эти bounds

Вам не прийдется мучиться с сихнронизацией тредов, а карта будет красиво экпандиться.
Вы меня извините, но ваше предложение ошибочно. Объясню почему. Код, который приведен выше полностью взят из примера (добавлены лишь метки с описанием) http://api.yandex.ru/maps/jsapi/examples/multiplygeocoding.html
Насколько я смог разобраться в построении карты, вся суть в модуле

YMaps.jQuery(function () {
   var map = new YMaps.Map(YMaps.jQuery(""#YMapsID"")[0]);
   map.setCenter(new YMaps.GeoPoint(7.64, 5.76), 4);
   map.addControl(new YMaps.Zoom());
   var data = [[""Москва"",""Описание 1""],[""Вадимир"",""Описание 2""]];

   bounds = new YMaps.GeoCollectionBounds();

   var geocoder = new MultiplyGeocoder(data); //

   map.addOverlay(geocoder);
   //map.setBounds(bounds);
   });


Ниже идет описание функции "MultiplyGeocoder", которая вызывает функцию "geocode". Вызов "YMaps.Events.observe(geocoder," происходит именно внутри этой функции. Писать там "map.setBounds(bounds);" не предоставляется возможным, поскольку внутри функции "geocode" map не видна. Если же там написать "_this.setBounds(bounds);", то это не приведет к желаемому результату (карта отцентрируется на "map.setCenter(new YMaps.GeoPoint(7.64, 5.76), 4);"). Мне не понятно почему переменная "bounds" остается пустой после вызова "MultiplyGeocoder(data);" если она объявлена как глобальная?
По сути  дает Вам правильный совет.


Геокодирование - операция асинхронная и масштабирование карты нужно выполнять только после ее завершения.
Попробуйте переместить map.setBounds(bounds)
на пару строк ниже в обработчик конца загрузки.
 
YMaps.Events.observe(geocoder, "Load", function () {
alert("Геокодирование завершено");
map.setBounds(bounds);
}


Все, я понял. Я изначально не правильно все понял спутав место, куда нужно вставить вызов "setBounds(bounds)". В моем коде у меня был удален данный обработчик и соответственно я не туда смотрел.
Все заработало, спасибо за ответы.

Столкнулся с такой же необходимостью

Не могли бы Вы выложить полный финальный код скрипта? Буду очень признателен. Да и многим будет полезно видеть готовое решение.

А расскажите, пожалуйста, зачем вам мультигеокодирование на стороне клиента?
Это же сложно, долго, и главное каждый раз.

У Вас PHP+MySQL?
Думаю будет сильно проще для Вас и ваших пользователей
прогеокодировать все объекты один раз и хранить их координаты в БД

У нас есть статья на эту тему
У меня 1с 8. Из нее я не знаю как обратиться к PHP+MySQL
Понятно. А объектов много?
Какой приблизительно порядок?

С 1с я не знаком, но этот метод можно использовать и без web-сервера.
Многие языки программирования имеют http-интерфейсы, например, Python.
Можно воспользоваться им или тем же PHP, просто запустив его в консоли как интерпретатор. Результат можно сохранить, например в csv или xml и загрузить в 1c 
Объектов порядка ста, но это не суть важно. Не обязательно отображать все сразу. Я нашел несколько примеров в которых описано как отображать только те, которые удовлетворяют некоторым условиям. Насколько я понял, правильным будет не кодировать объекты каждый раз, а хранить их координаты. Т.е. достаточно будет один раз прогнать все объекты через геокод и записать результаты в базу. А потом этим пользоваться
Забыл добавить. В 1с 8 есть возможность отображать на форме html-странички. Приведенный пример интересный, но я не знаю как его применить. Конечно как вариант можно хранить геокоординаты каждого клиента, но это другая тема. В данный момент меня интересует реализация первой задачи.