Блог API Яндекс.Карт

декабрь 2012
2.0 переключен на 2.0.20
4 декабря 2012, 14:41

Мы переключили ссылку api-maps.yandex.ru/2.0 на версию API 2.0.20. Если вы хотите продолжить использование предыдущей версии, указывайте api-maps.yandex.ru/2.0.18.

Рекомендуем прочитать статью о системе версионирования и использовать наиболее подходящую для ваших задач ссылку для подключения API.

Команда разработчиков API Яндекс.Карт.

6 комментариев
обновление,API 2.0
Пример: метки кластера в виде круговой диаграммы
5 декабря 2012, 15:06

Меткам кластеров в API 2.0 можно задавать различные иконки, а можно пойти еще дальше и сделать так, чтобы иконки кластеров зависели от типов меток, входящих в кластер. Мы сделали пример, уверены он будет вам полезен. 

Кластеры

Посмотреть пример в новом окне.

Пользуйтесь и присылайте свои примеры в комментариях, в клубе или на нашей страничке в Фейсбуке

60 комментариев
примеры,кластеризатор,API 2.0
Яндекс.Карты: + 175000 км² спутниковых снимков
6 декабря 2012, 13:56

Еще 175 000 км² спутниковых снимков для карт на ваших сайтах.

Яндекс.Карты: + 175000 км² спутниковых снимков

Сегодня спутниковое покрытие Яндекс.Карт увеличилось еще на 175 000 квадратных километров, относящихся к территориям России, Украины, Беларуси и Турции.

В России расширение коснулось БрянскойРязанскойРостовской областей, республик Марий Эл и Мордовия. Появилось много новых спутниковых снимков Беларуси. Вы можете подробно рассмотреть все крупные города Минской и Витебской областей.

Посмотрите полный список новых и обновленных городов. Особенно советуем обратить на него внимание любителям картографии, которые могут самостоятельно дополнить схемы городов на сервисе Народная карта.

Вот некоторые достопримечательности, которые были интересны нам самим:

1. Монастырь Хрещатик, Залещики



2. Византийская крепость в турецком городе Кютахья



3. Ратуша в белорусском городе Шклов



4. Институт культуры и искусств, Луганск



5. Мечеть с минаретом XVI века, Касимов




Команда Яндекс.Карт,
расширяем территорию

 

спутники,обновления карт
Интервью с Михаилом Хохловым: как разрабатывали прогнозирование для Яндекс.Пробок
7 декабря 2012, 15:36

Напоминаем, что 13 декабря в 19:00 московском офисе Яндекса Михаил Хохлов, разработчик инфраструктуры Яндекс.Пробок, проведет научно-технический семинар «Яндекс.Пробки: прогнозируем ситуацию на дороге».

Семинар бесплатный, но нужно зарегистрироваться.

А перед семинаром предлагаем вам почитать интервью с Михаилом о том, как разрабатывалась модель прогнозирования пробок, и какие трудности возникли в процессе.

 

Оригинал интервью размещен на страничке Яндекс.Мероприятия в фейсбуке. Для удобства читателей мы продублировали его и в нашем блоге.

Q: Миша, до изучения проблемы прогнозирования пробок, ты занимался системным анализом экономики в вычислительном центре РАН. Сложно ли было переключиться на новую тему исследований и помог ли предыдущий опыт?
 
A: Тема прогнозирования пробок меня сразу заинтересовала, поэтому переключиться было несложно. Эта область в чем-то похожа на прогнозирование в экономике, в ней ставятся похожие задачи, похожи и некоторые методы. Вообще, моделирование транспортных потоков – молодое и активно развивающееся направление, многие исследователи сейчас пытаются применять к нему подходы из самых разных областей науки. Опыт исследовательской деятельности, который я получил в ВЦ РАН, тут оказался очень кстати.
 
Q: Проводили ли вы какое-то специальное исследование, которое помогло создать математическую модель прогнозирования?
 
A: Естественно, прежде чем выбрать один из возможных подходов, мы изучили их особенности и сравнили на простых примерах. В качестве тренировки мы использовали прогноз по МКАД, взяв данные по нему за один месяц. Мы проверяли все наши модели и способы обработки данных, рисовали диаграммы и пытались понять, как устроены пробки на этой дороге. Большая часть полученных результатов оказалась применима и к другим магистралям, и даже к обычным городским улицам.
 
Q: С какими проблемами пришлось столкнуться во время разработки прогнозирования пробок?
 
A: Самым сложным, пожалуй, было выбрать наилучший метод из многих возможных. Для этого необходимо сформулировать какой-то критерий качества прогноза, а это, как оказалось, совсем не просто. Прогноз тем лучше, чем меньше его отклонение от реально наступившей ситуации, – это понятно. А вот дальше начинаются вопросы. Что лучше – точно предсказывать время поездки, но ошибаться в скорости, или наоборот? Сильно ошибаться для небольшого количества мест или умеренно ошибаться везде? Какой прогноз точнее: минимизирующий абсолютную ошибку (в секундах) или относительную (в процентах)? Каждый такой вопрос требует подробного анализа, прежде чем можно будет утверждать, что мы нашли оптимальный метод прогнозирования.
 
Q: Где-нибудь в мире еще используется прогнозирование пробок?
 
A: Сейчас во многих городах мира работают автоматические системы регулировки движения. Их задача – управлять движением с помощью светофоров, платных дорог, информационных табло так, чтобы максимально снизить нагрузку на транспортную систему и, соответственно, сэкономить время водителей. Для того чтобы делать это наиболее эффективно, им приходится учитывать не только текущую ситуацию на дорогах, но и пути ее возможного изменения. Поэтому, явно или неявно, прогноз обычно является составной частью такой системы. Кроме того, некоторые навигаторы могут давать рекомендации по выбору маршрута на основе имеющейся статистики пробок. Это тоже вариант прогноза (в Яндексе он известен под названием «пробки обычно»). Однако, по результатам наших экспериментов, при планировании поездки на ближайший час, такой прогноз дает не очень высокую точность.
 
Q: Чем отличаются от существующих аналогов Яндекс.Пробки?
 
A: Как я уже говорил, обычно системы прогнозирования пробок являются составной частью более крупных систем управления движением в городе. Они требуют тонкой подстройки под каждый конкретный город (иногда разработка такой системы с самого начала ориентирована на единственный город, в котором она будет применяться). Алгоритм прогноза, разработанный в Яндекс.Пробках, универсален в том смысле, что может без изменений применяться в любых регионах, из которых поступают данные, и как в городах, так и на междугородних трассах. Основным источником данных для него является информация, которую предоставляют нам наши пользователи. Это тоже отличает его от большинства аналогичных систем, которые требуют установки специальных детекторов транспортного потока непосредственно на дорогах.

 

2 комментария
пробки,анонсы,интервью
Пользовательские кнопки в API Яндекс.Карт 2.0
10 декабря 2012, 14:18

В API Яндекс.Карт 2.0 есть набор стандартных элементов управления картой: 



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

Марина Степанова (, @ya_mstepanova) разработчик API Яндекс.Карт, написала статью на Хабре, посвященную созданию собственных контролов. Это первый пост Марины на Хабре, поэтому мы будем рады вашей поддержке и комментариям.

Те, кому неудобно читать и комментировать статьи на Хабре, могут прочитать статью у нас в блоге.

 

Пользовательские кнопки в API Яндекс.Карт 2.0

Для того чтобы создать собственный макет элемента управления, нужно разобраться в части архитектуры API. В статье проводится краткий обзор понятий, с которыми должен ознакомиться разработчик перед выполнением этой задачи и объясняется общий принцип взаимодействия логической и визуальной части элементов управления. Также рассматриваются три примера по созданию макетов – от простого к сложному.


Статья рассчитана на разработчиков, которые уже имели опыт работы с API Яндекс.Карт 2.0. Для знакомства с основными концепциями рекомендую прочитать руководство разработчика.

 

Основные понятия

Что такое макет?

Макет – это визуальное представление элемента управления. По сути, макет – объект, который умеет на основе передаваемых ему данных генерировать html.

Макет получает на вход объект с полями:

— control — ссылка на элемент управления;

— options — менеджер опций элемента управления;

— data — менеджер данных элемента управления;

— state — менеджер состояния элемента управления.

 

Что такое менеджер опций (состояния, данных)?

Менеджер – это хранилище, которое позволяет устанавливать и получать значения по ключу. Менеджер опций также умеет получать опции от родительских элементов, если они не найдены у ребенка.

Получать и задавать опции или данные можно следующим образом:

smallZoomControl.options.get(‘layout’); // получаем опцию layout
smallZoomControl.data.set(‘publicId’, myId); // запись произвольного поля в менеджер данных
В чем разница между опциями, данными и состоянием?

Опции – это рекомендации ко внешнему виду элемента управления. Например, через опции задается класс макета ('layout'), минимальная ширина кнопки ('minWidth') и т.д.
Важная особенность опций – возможность наследования от родителей. То есть опции можно задавать как напрямую, так и через любой из родительских элементов. При задании опций через родительские элементы, как правило, используется префикс. Например, опцию ’layout’ для control.Button можно задать через карту как ‘buttonLayout’ (‘button’ + ‘layout’).

Данные – это набор полей, описывающих информационное содержимое элемента. Например, данными может являться заголовок списка ('title') или содержимое кнопки ('content'). Данные не наследуются от родительских элементов и задаются только напрямую в объект.


Состояние – это набор полей, описывающих текущее состояние элемента управления. Поля состояния могут изменяться в результате действий пользователя.
Примеры полей состояния:

— 'expanded' — признак, раскрыт или свернут выпадающий список;

— 'selected' — признак, нажата или отжата кнопка.

Поля состояния также не наследуются от родительских элементов и могут самостоятельно изменяться в результате действий над элементом управления (например, в результате вызова метода button.select() изменится поле состояния кнопки ‘selected’).

Пример 1. Формирование макета на основе данных, опций и состояния элемента управления

Чаще всего макеты создаются с помощью специальной фабрики templateLayoutFactory. Фабрика позволяет задавать текстовый шаблон, с помощью которого впоследствии будет сформировано dom-представление элемента.

Рассмотрим пример создания собственного макета для control.Button. Что мы хотим получить от созданного макета:

1. В кнопке должна быть какая-то надпись;

2. У кнопки есть 2 состояния – когда она нажата и когда она не нажата.

Надпись – это значение одного из полей данных кнопки. Стандартная реализация кнопки использует поле 'content':

myButton.data.get(‘content’);

Нам ничего не мешает использовать другое произвольное поле данных, если это необходимо. Например:

myButton.data.set(‘caption’, ‘Сохранить’);

В данном случае обойдемся стандартным полем данных.

В нашем примере dom-представлением кнопки будет являться элемент div:

<div class=’my-button’>Заголовок кнопки</div>

Итак, нужно, чтобы вместо фразы ‘Заголовок кнопки’ подставилось поле из данных элемента управления. Создание макета кнопки будет выглядеть следующим образом:

var ButtonLayout = ymaps.templateLayoutFactory.createClass("<div class='my-button'> $[data.content] </div>");

Вместо текста 'Заголовок кнопки' мы вставили шаблон '$[data.content]'.

Фабрика макетов умеет обращаться с менеджерами данных, опций или состояний. Поэтому мы обращаемся к полю ‘content’ через точку – фабрика самостоятельно сможет определить, что data является менеджером данных, и выполнить операцию data.get(‘content’).

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


С первым пунктом мы справились. Переходим к пункту два.

В обычном состоянии кнопка выглядит так:

<div class=’my-button’>Заголовок кнопки</div>

В нажатом состоянии она выглядит так:

<div class=’my-button my-button-selected’>Заголовок кнопки</div>

То есть элементу div дописывается специальный класс, который меняет внешний вид кнопки.

Модифицируем наш текстовый шаблон:

var ButtonLayout = ymaps.templateLayoutFactory.createClass("<div class='my-button 
[if state.selected]my-button-selected[endif]'>$[data.content]</div>");

Итак, на основе данных и состояния кнопки мы смогли создать ее макет. Макет кнопки автоматически реагирует на клики и транслирует их в элемент управления. Так что никакой дополнительной логики в данном примере не требуется.

Посмотреть пример.

Пример 2. Макет, который взаимодействует с элементом управления

Рассмотрим более сложный пример – создание элемента управления коэффициентом масштабирования карты, проще говоря — 'зум-контрола'.

Html-шаблон нашего элемента управления выглядит так:

<div>
     <div id='zoom-in'>+</div>
     <div id='zoom-out'>-</div>
</div>

От созданного макета мы хотим получить следущее – при клике на элемент с плюсом или минусом нужно увеличивать или уменьшать зум карты на 1.

В документации сказано, что макет control.SmallZoomControl реализует интерфейс IZoomControlLayout. Читаем описание интерфейса и находим описание события 'zoomchange':

Zoomchange — cобытие, инициирующее смену коэффициента масштабирования карты. Экземпляр класса Event. Имена полей, доступных через метод Event.get:

— newZoom — новое значение коэффициента масштабирования;

— oldZoom — старое значение коэффициента масштабирования.

Это означает следующее – когда макет посылает событие ‘zoomchange’, элемент управления ловит его и соответственно реагирует (то есть изменяет коэффициент масштабирования карты).

Нужно, чтобы после формирования html макета на определенные элементы были навешаны слушатели. В частности, нужно слушать события ‘click’ на элементах с id=’zoom-in’ и id=’zoom-out’. В обработчиках клика мы будем генерировать событие 'zoomchange', в поля которого будут передаваться старый и новый коэффициенты масштабирования карты.

Создание макета для зум-контрола будет выглядеть следующим образом:

// Создадим пользовательский макет ползунка масштаба.
var MyZoomLayout = ymaps.templateLayoutFactory.createClass("<div>" +
            "<div id='zoom-in'>+</div>" +
            "<div id='zoom-out'>-</div>" +
        "</div>", {

        // Переопределяем методы макета, чтобы выполнять дополнительные действия
        // при построении и очистке макета.
        build: function () {
            // Вызываем родительский метод build.
            MyZoomLayout.superclass.build.call(this);

            // Начинаем слушать клики на кнопках макета.
            $('#zoom-in').bind('click', ymaps.util.bind(this.zoomIn, this));
            $('#zoom-out').bind('click', ymaps.util.bind(this.zoomOut, this));
        },

        clear: function () {
            // Снимаем обработчики кликов.
            $('#zoom-in').unbind('click');
            $('#zoom-out').unbind('click');

            // Вызываем родительский метод clear.
            MyZoomLayout.superclass.clear.call(this);
        },

        zoomIn: function () {
            var map = this.getData().control.getMap();
            // Генерируем событие, в ответ на которое
            // элемент управления изменит коэффициент масштабирования карты.
            this.events.fire('zoomchange', {
                oldZoom: map.getZoom(),
                newZoom: map.getZoom() + 1
            });
        },

        zoomOut: function () {
            var map = this.getData().control.getMap();
            this.events.fire('zoomchange', {
                oldZoom: map.getZoom(),
                newZoom: map.getZoom() - 1
            });
        }
  });

Посмотреть пример

На примере control.SmallZoomControl мы рассмотрели, как взаимодействуют элемент управления и его макет. Обобщим полученные знания в схеме:

Макет элемента управления строится на основе полей 'state', 'data' или 'options' и следит за их изменениями. При изменении значений полей макет перестраивается.

Макет, в свою очередь, может менять состояние элемента управления с помощью событий, которые указаны в его интерфейсе. Элемент управления слушает указанный набор событий и выполняет (или не выполняет) соответствующие действия.

Пример 3. Создание макета группового элемента управления

Групповой элемент управления отличается тем, что в него можно добавлять дочерние элементы. Макет группового элемента, таким образом, должен иметь html-элемент, который будет являться корневым для html-макетов дочерних элементов.

Создадим макет для выпадающего списка.

Html-макет раскрытого списка выглядит следующим образом:

<div id='my-listbox-header'>Заголовок списка</div>
<div id='my-listbox’>
    Первый элемент списка<br/>
    Второй элемент списка<br/>
</div>

Выпишем, что мы хотим получить от готового макета:

1. Нужно, чтобы в макет подставлялся заголовок списка;
2. Нужно, чтобы дочерние элементы списка автоматически добавлялись в указанный dom-элемент родителя;
3. Наш список должен уметь сворачиваться и разворачиваться;
4. Нужно каким-то образом задать внешний вид элементам списка.

Подставлять в макет заголовок списка мы будем по аналогии с примером макета кнопки:

var MyListBoxLayout = ymaps.templateLayoutFactory.createClass(
        "<div id='my-listbox-header'>$[data.title]</div>” +
        “<div id='my-listbox’></div>"
    );

Теперь перейдем ко второму пункту.

Родительским dom-элементом в нашем выпадающем списке будет элемент <div id='my-listbox’>.

Макет группового элемента управления должен реализовывать интерфейс IGroupControlLayout. Особенность этого интерфейса – наличие метода getChildContainerElement. Через этот метод элемент управления получает dom-элемент, к которому ему нужно прикреплять html-макеты дочерних элементов.

var MyListBoxLayout = ymaps.templateLayoutFactory.createClass(
        "<div id='my-listbox-header'>$[data.title]</div>” +
        “<div id='my-listbox’ ></div>", {
        build: function() {
            MyListBoxLayout.superclass.build.call(this);
            this.childContainerElement = $('#my-list-box')[0];
        },

        getChildContainerElement: function () {
            return this.childContainerElement;
        }
    });


При построении макета будет найден нужный dom-элемент, и групповой элемент управления сможет добавить дочерние элементы к родительскому.

Поскольку наш макет содержит подстановку '$[data.title]', он может перестраиваться. Как только это поле будет изменено, макет вызовет пару методов clear и build, чтобы обновить свое html-отображение. В таком случае dom-элемент, который служит контейнером для дочерних элементов, изменится (да, он будет точно такой же, как предыдущий, но это физически будет другой dom-элемент).

Элемент управления не следит за изменениями макета, и не узнает о том, что контейнер дочерних элементов сменился. Поэтому нам необходимо самостоятельно оповестить его об этом.

Каждый раз при перестроении будем генерировать событие интерфейса IGroupControlLayout 'childcontainerchange'.

var MyListBoxLayout = ymaps.templateLayoutFactory.createClass(
        "<div id='my-listbox-header'>$[data.title]</div>” +
        “<div id='my-listbox’></div>", {
        build: function() {
            MyListBoxLayout.superclass.build.call(this);
            this.childContainerElement = $('#my-list-box')[0];
            // Генерируем специальное событие, оповещающее элемент управления
            // о смене контейнера дочерних элементов.
            this.events.fire('childcontainerchange', {
                newChildContainerElement: this.childContainerElement,
                oldChildContainerElement: null
            });
        },

        clear: function () {
            // Заставим элемент управления перед очисткой макета
            // откреплять дочерние элементы от родительского.
            // Это защитит нас от неожиданных ошибок,
            // связанных с уничтожением dom-элементов в ранних версиях ie.
            this.events.fire('childcontainerchange', {
                newChildContainerElement: null,
                oldChildContainerElement: this.childContainerElement
            });
            this.childContainerChange = null;
            MyListBoxLayout.superclass.clear.call(this);
        },

        getChildContainerElement: function () {
            return this.childContainerElement;
        }
    });

Теперь при перестроении макета элемент управления будет знать о смене контейнера и переносить дочерние элементы в новый dom-элемент.


Нужно сделать так, чтобы наш список умел сворачиваться и разворачиваться.

Внешний вид элемента управления в свернутом состоянии:

<div id='my-listbox-header'>Заголовок списка</div>

Внешний вид элемента управления в развернутом состоянии:

<div id='my-listbox-header'>Заголовок списка</div>
<div id='my-listbox’>
    Первый элемент списка<br/>
    Второй элемент списка<br/>
</div>

Получается, что в данном примере (в зависимости от состояния элемента управления) нужно показывать или скрывать контейнер с дочерними элементами.

var MyListBoxLayout = ymaps.templateLayoutFactory.createClass(
        "<div id='my-listbox-header'>$[data.title]</div>” +
        “<div id='my-listbox’ style='display: [if state.expanded]block[else] none[endif];’></div>", {
        build: function() {
            MyListBoxLayout.superclass.build.call(this);
            this.childContainerElement = $('#my-list-box')[0];
            // Генерируем специальное событие, оповещающее элемент управления
            // о смене контейнера дочерних элементов.
            this.events.fire('childcontainerchange', {
                newChildContainerElement: this.childContainerElement,
                oldChildContainerElement: null
            });
        },

        clear: function () {
            // Заставим элемент управления перед очисткой макета
            // откреплять дочерние элементы от родительского.
            // Это защитит нас от неожиданных ошибок,
            // связанных с уничтожением dom-элементов в ранних версиях ie.
            this.events.fire('childcontainerchange', {
                newChildContainerElement: null,
                oldChildContainerElement: this.childContainerElement
            });
            this.childContainerChange = null;
            MyListBoxLayout.superclass.clear.call(this);
       },

      getChildContainerElement: function () {
          return this.childContainerElement;
     }
});


Мы настроили макет, который реагирует на изменение состояния элемента управления. Теперь нужно настроить обратную связь – в зависимости от действий пользователя посылать элементу управления команды «свернуться» или «развернуться». К счастью, control.ListBox по умолчанию сворачивается или разворачивается по клику на макете. Так что в данном примере никаких дополнительных действий для этого совершать не надо. Если бы нас не устроило поведение по умолчанию, мы могли бы самостоятельно отправлять команды элементу управления через макет, как мы это делали с control.SmallZoomControl.

Осталось создать макет для элементов выпадающего списка. Это делается довольно просто.

ymaps.templateLayoutFactory.createClass("$[data.content]<br/>");

Посмотреть пример

Еще один пример реализации пользовательских макетов





Для демонстрации возможностей макетов мы отобрали шесть самых популярных элементов управления картой в API (Кнопка, Раскрывающийся список, Поиск по карте, Простой элемент управления масштабом карты, Панель управления пробками, и Переключатель типа карты) и изменили их дизайн с помощью популяного css-фреймворка Twitter Bootstrap.

Посмотреть пример

Код на гитхабе

 

статьи,контролы,элементы управления,API 2.0
Перенос вебинара «API Яндекс.Карт для интернет-магазинов»
11 декабря 2012, 14:38

Анонсированный на 11 декабря вебинар переносится на 18 декабря

Напоминаем, что вебинар будет посвящен использованию Яндекс.Карт на сайтах интернет-магазинов.

Катя Текунова (, @tekunova), маркетолог API, расскажет, какие разделы сайта интернет-магазина можно значительно улучшить с помощью карты, а также покажет простые инструменты для создания такой карты.

Участие в вебинаре бесплатное, но нужно зарегистрироваться. Дополнительно о вебинаре можно почитать на сайте events.yandex.ru.

В этот раз мы попробуем новый формат. Подключайтесь, будет интересно!

Катя
1 комментарий
вебинар,анонсы
Пример: индексирование вершин ломаной линии
12 декабря 2012, 14:12

По просьбе пользователя клуба разработчиков сделали пример, в котором при построении ломаной линии каждой ее вершине присваивается определенная метка.

Посмотреть пример в новом окне.

Индексация вершин ломаной

Пользуйтесь и присылайте свои примеры в комментариях, в клубе или на нашей страничке в Фейсбуке.

примеры,ломаная,API 2.0
Версия 2.0.21
13 декабря 2012, 17:43

Опубликована новая версия API Яндекс.Карт. Она доступна по адресу api-maps.yandex.ru/2.0.21. Во вторник, 18 декабря, мы переключим на нее api-maps.yandex.ru/2.0. Если вы хотите продолжить использование предыдущей версии, указывайте api-maps.yandex.ru/2.0.20.

Пожалуйста, прочтите статью о системе версионирования API.

Добавлено:

— Базовые геометрии.

— В шаблонных макетах балуна и хинта геообъектов можно использовать значения из geoObject.options, geoObject.state, geoObject.properties.

— Метод once в менеджерах событий.

Исправлено:

— При заполнении boundedBy при геокодировании не учитывался порядок координат.

— Исключение, возникающее после уничтожения карты.

— Невозможность задать в позиции элементов управления bottom: 0 и right: 0.

— На ymaps.control.Button не происходили некоторые события, если кнопка не была добавлена на карту.

— Исключение в шаблонных макетах при подстановке значения null.

— Не изменялись координаты объектов, находящихся в неподвижных контейнерах.

— Неправильное определение zoomRange в некоторых ситуациях.

— Исключение при удалении раскрытого control.ListBox.

— Пропадание control.RollupButton в некоторых ситуациях.

— Ошибки реализации VML-графики в Internet Explorer.

— autoPan в балуне не учитывал значение balloonOffset.

— Дублирование многоугольников в некоторых ситуациях.

— Исключение при щелчке правой кнопкой мыши над хинтом линейки.

— Макеты twirl#*StretchyIcon не пересчитывали свои размеры при инициализации в скрытом блоке.

Команда разработчиков API Яндекс.Карт.

обновление,API 2.0
Большое обновление карт Москвы и Санкт-Петербурга
14 декабря 2012, 15:19

Обновленные карты Москвы, Московской области и Санкт-Петербурга для ваших сайтов.

Большое обновление карт Москвы и Санкт-Петербурга

Облик городов постоянно изменяется. Строятся новые жилые кварталы, торговые центры, открываются станции метро, появляются транспортные развязки и новые трассы. Все эти изменения мы стараемся своевременно отобразить на наших картах.

Сегодня у нас большое обновление карт Москвы и Санкт-Петербурга. Эти карты нарисованы непосредственно в Яндексе, именно поэтому в них добавлено много нового и актуального.

В Москве мы добавили строящиеся станции метро – "Пятницкое шоссе" и "Алма-Атинскую" – и вестибюль станции "Марьина Роща".

Для тех москвичей, кто передвигается на автомобиле, мы отметили новые дублеры на Варшавском и Каширском шоссе, развязку МКАД и Ленинградского шоссе, а также другие изменения как на крупнейших магистралях, так и на обычных улицах. А еще мы начали наносить на карту строящиеся дороги – поэтому теперь вы можете полюбоваться на строительство трассы в обход Одинцово.

Кроме того, мы внимательно следим за строительством новых жилых комплексов – например, таких как «Большое Кусково», «Мичуринский», «Виноградный».

Мы обновили также карты городов Московской области. Заметнее других изменились – Воскресенск, Звенигород, Ногинск, Павловский Посад, Пересвет, Сергиев Посад, Черноголовка, Электросталь. Добавили новые торговые центры – ТЦ «Глобус» в Королеве или ТЦ «Октябрьский» в Подольске. А поселок Фряново получил полноценную карту с домами, поиском адресов и названиями улиц.

В Санкт-Петербурге после обновления на картах появились две новых станции метро – «Бухарестская» и «Международная», открытие которых ожидается в ближайшие две недели.
Дорожная сеть на карте стала больше на 100 километров и достигла 16 тыс. 708 км. В обновлении учтены важнейшие новостройки, например, путепроводы на Приморском шоссе или реконструированный участок набережной Обводного канала.

Как всегда, мы добавили на карту много новых адресов и домов. Если же вашего дома все еще нет, вы можете нарисовать его на Народной карте или написать нам – и мы постараемся это исправить. Например, в этом релизе учтено более 5000 комментариев от пользователей, поступивших за последние два-три месяца.

Все обновления доступны в мобильных Яндекс.Картах.


Команда Яндекс.Карт,
следим за изменениями

обновления карт
Пример: отображение статуса метки кластера
17 декабря 2012, 13:41

Мы решили расширить пример «Метки кластера в виде круговой диаграммы» и добавили в него таблицу, которая позволяет отслеживать, добавлена ли метка на карту и входит ли она в кластер.

Статусы меток

Посмотреть пример в новом окне.

Пользуйтесь и присылайте свои примеры в комментариях, в клубе или на нашей страничке в Фейсбуке

16 комментариев
примеры,кластеризатор,API 2.0
2.0 переключен на 2.0.21
18 декабря 2012, 14:06

Мы переключили ссылку api-maps.yandex.ru/2.0 на версию API 2.0.21. Если вы хотите продолжить использование предыдущей версии, указывайте api-maps.yandex.ru/2.0.20.

Рекомендуем прочитать статью о системе версионирования и использовать наиболее подходящую для ваших задач ссылку для подключения API.

Команда разработчиков API Яндекс.Карт.

7 комментариев
«Затор и покраснение» — интервью про пробки Ленте.ру
19 декабря 2012, 19:39

О том, как Яндекс собирает данные о пробках и прогнозирует их, можно рассказывать бесконечно. На это раз Михаил Хохлов, разработчик Яндекс.Пробок дал подробное интервью Ленте.ру.

Как отобразить пробки на карте на вашем сайте, читайте в документации в разделах control.TrafficControl и traffic.provider.Actual.

интервью,пробки,API 2.0
Запись семинара «Математическая модель для прогнозирования пробок»
20 декабря 2012, 19:09

В последнее время довольно много постов были посвящены сбору информации о пробках и их прогнозу. Перед новым годом тема загруженности дорог очень актульна. Сегодня мы предлагаем посмотреть видео и презентацию с семинара Михаила Хохлова «Математическая модель для прогнозирования пробок».

 

презентации,видео,пробки
Как мы заставили API Яндекс.Карт работать быстрее
21 декабря 2012, 14:49

Видео с выступления Марины Степановой (, @ya_mstepanova), разработчика API Яндекс.Карт на Я.Субботнике в Санкт-Петербурге. Марина рассказывает о том, почему стоит избегать преждевременных оптимизаций, о методиках измерения скорости и о том, за счет чего мы все-таки ускорили работу нашего API. Видеозаписи других докладов смотрите в клубе Я.Субботника.

Также вы можете скачать видео (1,77 ГБ), презентацию (PDF, 17,9 МБ) или мобильное видео (208,8 МБ).


презентации,видео,Я.Субботник,API 2.0
Добавление меток пользователями сайта и вывод их по категориям — часть 3
24 декабря 2012, 14:44

В блоге «Занимательная веб-картография» опубликована новая статья «Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями и вывод по категориям». В этой заметке автор рассказывает, как настраивать фильтры для объектов, которые добавили на ваш сайт сами пользователи. Предыдущая статья посвящена добавлению меток и сохранению их в базу.

P.S.: Если вы написали статью или хотите рассказать о своей реализации, пишите нам в клубfacebook или на почту ymapsapi@ya.ru.

5 комментариев
статьи,API 2.0,фильтрация,метки,статьи пользователей
Пример: формирование ссылки на фрагмент карты
26 декабря 2012, 18:36

Мы переделали под вторую версию API популярный старый пример «Формирование ссылки на фрагмент карты». А также добавили возможность сохранить в истории состояние карты с помощью HTML5 History API. Данная функциональность может потребоваться, если на карте размещены объекты, а пользователям необходимо обмениваться ссылками на фрагменты карты с этими объектами.

Посмотреть пример в новом окне.

Пользуйтесь и присылайте свои примеры в комментариях, в клубе или на нашей страничке в Фейсбуке

3 комментария
примеры,ссылка на карту,API 2.0
Создание меню для отображения коллекций геообъектов
28 декабря 2012, 16:36

В последнее время в клубе нас часто спрашивают различные варианты примера меню для групп геообъектов. Так как все возможные кейсы предусмотреть невозможно, мы решили написать статью и по шагам объяснить подход к созданию такого меню.
Чтобы задать логику элементам меню, нужно связать его DOM-представление с ссылкой на объект API, с которым этот пункт меню будет взаимодействовать. Мы будем слушать событие 'click' на DOM-элементе и удалять или добавлять соответствующий геообъект с карты через API.


Построение меню из массива исходных данных

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

Допустим у нас есть такой массив исходных данных:



// Группы объектов
var groups = [{
name: "Известные памятники",
preset: "twirl#redIcon",
style: "important",
items: [{
center: [50.426472, 30.563022],
name: "Монумент 'Родина-Мать'"
}, {
center: [50.45351, 30.516489],
name: "Памятник Богдану Хмельницкому"
}, {
center: [50.454433, 30.529874],
name: "Арка Дружбы народов"
}]
}, {
name: "Покушайки",
preset: "twirl#greenIcon",
style: "success",
items: [{
center: [50.50955, 30.60791],
name: "Ресторан 'Калинка-Малинка'"
}, {
center: [50.429083, 30.521708],
name: "Бар 'Сало-бар'"
}, {
center: [50.450843, 30.498271],
name: "Абсент-бар 'Палата №6'"
}, {
center: [50.454834, 30.516498],
name: "Ресторан 'Спотыкач'"
}]
}, {
name: "Оригинальные музейчики",
preset: "twirl#orangeIcon",
style: "warning",
items: [{
center: [50.443334, 30.520163],
name: "Музей грамзаписи и старинных музыкальных инструментов"
}, {
center: [50.446977, 30.505269],
name: "Музей истории медицины или Анатомический театр"
}, {
center: [50.452512, 30.530889],
name: "Музей воды. Водно-информационный центр"
}]
}, {
name: "Красивости",
preset: "twirl#blueIcon",
style: "info",
items: [{
center: [50.45987, 30.516174],
name: "Замок Ричарда-Львиное сердце"
}, {
center: [50.445049, 30.528598],
name: "'Дом с химерами'"
}, {
center: [50.449156, 30.511809],
name: "Дом Рыцаря"
}]
}];


Чтобы создать на его основе меню и маркеры на карте, нам необходимо в цикле перебирать элементы этого массива, например, с помощью стандартного метода forEach:


// Контейнер для меню.
var menu = $('<ul class="nav nav-list"/>');
// Перебираем все группы.
groups.forEach(function (group) {
// DOM-представление группы.
var menuItem = $('<li class="nav-header">' + group.name + ''),
// Создадим коллекцию для геообъектов группы.
collection = new ymaps.GeoObjectCollection(null, { preset: group.preset });
});


Для каждого элемента массива, представляющего собой описание группы геообъектов, мы создаем DOM-представление в виде элемента меню и представление на карте: коллекцию. Затем мы добавляем коллекцию на карту, а элемент — в меню. Мы будем обрабатывать клики на элементе и при их возникновении будем удалять или добавлять соответствующую коллекцию на карту, а также скрывать или отображать подменю.


// Добавляем коллекцию на карту.
myMap.geoObjects.add(collection);
menuItem
// Добавляем пункт в меню.
.appendTo(menu)
// Навешиваем обработчик клика по пункту меню.
.on('click', function (e) {
// Скрываем/отображаем пункты меню данной группы.
$(this)
.nextUntil('.nav-header')
.removeClass('active')
.slideToggle('fast');
// Скрываем/отображаем коллекцию на карте.
if (collection.getParent()) {
myMap.geoObjects.remove(collection);
} else {
myMap.geoObjects.add(collection);
}
});


Далее мы обрабатываем все элементы группы также с помощью forEach:


// Перебираем элементы группы.
group.items.forEach(function (item) {
// DOM-представление элемента группы.
var menuItem = $('<li><a href="javascript:void(0)">' + item.name + '</a></li>'),
// Создаем метку.
placemark = new ymaps.Placemark(item.center, { balloonContent: item.name });
// Добавляем метку в коллекцию.
collection.add(placemark);
menuItem
// Добавляем пункт в меню.
.appendTo(menu)
// Навешиваем обработчик клика по пункту меню.
.on('click', function (e) {
// Отменяем основное поведение (переход по ссылке)
e.preventDefault();
// Выставляем/убираем класс active.
menuItem
.toggleClass('active')
.siblings('.active')
.removeClass('active');
// Открываем/закрываем баллун у метки.
if (placemark.balloon.isOpen()) {
placemark.balloon.close();
} else {
// Плавно меняем центр карты на координаты метки.
myMap.panTo(placemark.geometry.getCoordinates(), {
delay: 0,
callback: function () {
placemark.balloon.open();
}
});
}
});
});


Здесь по аналогии мы создаем API-представление для каждого элемента группы в виде метки, которую добавляем в API-представление группы (коллекцию), и DOM-представление в виде элемента меню, который добавляем в меню после пункта соответствующей группы. Затем навешиваем на него обработчик события 'click', при возникновении которого будем открывать или закрывать балун у метки, а также менять центр карты.

После обработки всех данных нам остается добавить меню на страницу и установить область видимости карты в соответствии с её содержимым:


// Добавляем меню в сайдбар.
menu.appendTo($('#sidebar'));
// Выставляем масштаб карты чтобы были видны все группы.
myMap.setBounds(myMap.geoObjects.getBounds());


Итоговый код можно посмотреть тут.

Построение меню на основе YMapsML-файла

Этот вариант является достаточно распространенным, т.к. довольно удобно хранить коллекции геообъектов в формате XML у себя на сервере или на maps.yandex.ru в Моих картах. Реализовать его, пожалуй, даже проще в связи с тем, что geoXML-загрузчик возвращает нам готовые API-коллекции геообъектов, которые нам остается только добавить на карту.


// Загрузка YMapsML-файла.
ymaps.geoXml.load("http://api.yandex.ru/maps/doc/ymapsml/1.x/examples/xml/menufromymapsml.xml")
.then(function (res) {
// Все содержимое YMapsML файла возвращается ввиде коллекции.
var groups = res.geoObjects,
// Стили для DOM-представлений групп.
styles = {
"default#redPoint": "important",
"default#greenPoint": "success",
"default#orangePoint": "warning",
"undefined": "info"
};
// Добавляем все группы на карту.
myMap.geoObjects.add(groups);
});


Для построения меню нам нужно перебирать эти коллекции, например, с помощью метода each или итератора. Затем, получив в обработчике элементы коллекции, строить по ним пункты меню, связывая их с геообъектами посредством интерфейса DOM-событий.
Данные для пунктов меню (название) в этом варианте мы получаем из данных геообъектов и коллекций.


// Перебираем все группы.
groups.each(function (group) {
// Определяем стиль для группы.
var preset = group.options.get('preset') || 'twirl#blueIcon',
style = styles[preset.match(/#([a-z]+)[A-Z]/)[1]],
// Имя группы.
name = group.properties.get('name'),
// DOM-представление группы.
menuItem = $('<li class="nav-header">' + name + '');
menuItem
// Добавляем пункт в меню.
.appendTo(menu)
// Навешиваем обработчик клика по пункту меню.
.on('click', function (e) {
// Скрываем/отображаем пункты меню данной группы.
$(this)
.nextUntil('.nav-header')
.removeClass('active')
.slideToggle('fast');
// Скрываем/отображаем коллекцию на карте.
if (group.getParent()) {
groups.remove(group);
} else {
groups.add(group);
}
});
});


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


// Перебираем элементы группы.
group.each(function (item) {
var name = item.properties.get('name'),
// DOM-представление элемента группы.
menuItem = $('<li><a href="javascript:void(0)">' + name + '</a></li>');
// Добавляем пункт в меню.
menuItem
.appendTo(menu)
// Навешиваем обработчик клика по пункту меню.
.on('click', function (e) {
e.preventDefault();
// Выставляем/убираем класс active.
menuItem
.toggleClass('active')
.siblings('.active')
.removeClass('active');
// Открываем/закрываем балун у метки.
if (item.balloon.isOpen()) {
item.balloon.close();
} else {
// Плавно меняем центр карты на координаты метки.
myMap.panTo(item.geometry.getCoordinates(), {
delay: 0,
callback: function () {
item.balloon.open();
}
});
}
});
});


Итоговый пример можно посмотреть тут.

Подключение существующего меню к геообъектам на карте

Если меню на странице уже есть, и нужно просто связать его пункты с геообъектами на карте. В этом случае мы можем раздать геообъектам и соответствующим пунктам меню уникальные идентификаторы, а по клику на пункт меню искать соответствующий ему геообъект по этому идентификатору.

Это можно сделать, проставив DOM-элементам атрибуты id, а геообъектам передать произвольное поле в объекте-данных (поле properties в первом параметре в конструкторе коллекции и второй параметр в конструкторе метки).

Таким образом создание коллекции с названием и идентификатором будет выглядеть следующим образом:


var group1 = new ymaps.GeoObjectArray({
properties: {
id: 'group-1',
name: 'Известные памятники'
}
}, {
preset: 'twirl#redIcon'
});


Далее наполним коллекцию метками с помощью метода add:


group1
.add(new ymaps.Placemark([50.426472, 30.563022], { id: 'group-1-1', balloonContent: 'Монумент "Родина-Мать"' }))
.add(new ymaps.Placemark([50.45351, 30.516489], { id: 'group-1-2', balloonContent: 'Памятник "Богдану Хмельницкому"' }))
.add(new ymaps.Placemark([50.454433, 30.529874], { id: 'group-1-3', balloonContent: 'Арка Дружбы народов' }));


Поскольку в данном примере мы не будем хранить ссылки на коллекции, мы поместим наши коллекции в еще одну коллекцию, назовем ее visible и добавим ее на карту. Чтобы скрыть коллекции с карты мы будем переносить их (добавлять) в другую коллекцию, назовем ее hidden, которую мы не будем добавлять на карту. Стоит отметить в API все геообъекты и коллекции реализуют интерфейс IChildOnMap. Следовательно добавление геообъекта или коллекции в другую коллекцию удалит его из текущей коллекции. В нашем случае перенос коллекции геообъектов из visible в hidden приведет к удалению этой коллекции с карты.


// Добавляем все группы в одну коллекцию.
visible
.add(group1)
.add(group2)
.add(group3)
.add(group4);
// Добавляем все группы на карту.
myMap.geoObjects.add(visible);


Теперь если мы добавим коллекцию group1 в другую коллекцию hidden,


hidden.add(group1);


она автоматически будет удалена из коллекции visible и соответственно с карты.

Поместим код управления видимостью коллекций на карте в отдельный метод groupToggle, принимающий идентификатор коллекции.


// Ищем нужную группу и добавляем/удаляем ее с карты.
function groupToggle (id) {
// Все группы лежат внутри одной коллекции, которую мы получили из YMapsML.
var it, group;
// Сначала ищем в видимой на карте коллекции.
it = visible.getIterator();
while (group = it.getNext()) {
if (group.properties.get('id') === id) {
hidden.add(group);
return;
}
}
// Если мы сюда попали, значит коллекция уже удалена и надо искать в удаленных.
it = hidden.getIterator();
while (group = it.getNext()) {
if (group.properties.get('id') === id) {
visible.add(group);
return;
}
}
}


В данном методе мы будем использовать итератор вместо уже знакомого нам метода each. Он имеет преимущество, так как мы можем при нахождении нужного элемента завершить перебор коллекции и выйти из функции вызовом return.

Обработчик клика на DOM-представлении коллекций будет выглядеть следующим образом:


$('.nav-header').on('click', function (e) {
// Скрываем/отображаем пункты меню данной группы.
$(this)
.nextUntil('.nav-header')
.removeClass('active')
.slideToggle('fast');
// Скрываем/отображаем коллекцию на карте.
groupToggle(this.id);
});


Для обработки кликов по пунктам меню, которые связаны с элементами группы, будем использовать следующий код:


// Обрабатываем клики на пунктах меню элементов группы.
$('li:not(.nav-header)').on('click', function (e) {
// Отменяем основное поведение (переход по ссылке)
e.preventDefault();
$(this)
.toggleClass('active')
.siblings('.active')
.removeClass('active');
itemToggle(this.id);
});


В методе itemToggle также будем использовать итераторы:


// Ищем нужную метку и открываем/закрываем ее балун.
function itemToggle (id) {
var it = visible.getIterator(),
group;
while (group = it.getNext()) {
for (var i = 0, len = group.getLength(); i < len; i++) {
var placemark = group.get(i);
if (placemark.properties.get('id') === id) {
if (placemark.balloon.isOpen()) {
placemark.balloon.close();
} else {
myMap.panTo(placemark.geometry.getCoordinates(), {
delay: 0,
callback: function () {
placemark.balloon.open();
}
});
}
return;
}
}
}
}


Итоговый пример можно посмотреть тут.

12 комментариев
примеры,статьи,фильтрация,API 2.0