Клуб API Карт

Событие перетаскивания карты пользователем, api 2.0

Пост в архиве.

Добрый день. Как отловить событие перетаскивания карты пользователем?  

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

22 комментария
Удалённый пользователь
28 января 2016, 02:54

Я бы попробовал выкрутиться так:

отключить flight во всех panTo

и присвоить событиям actionend и wheel вашу ф-цию.

 

а что это даёт?

после panTo([x, y], {flying: false}) все равно срабатывает actionend, а хотелось бы чтоб не срабатывал

Удалённый пользователь
28 января 2016, 02:54

печально на самом деле, ведь  документации написанно:


Началось новое плавное движение карты

а если flying: false, то оно по идее не должно быть плавным =\


 

оно при setCenter() не плавное, однако actionend опять же срабатывает

В общем вышел из ситуации использованием трёх событий mousedown, mousemove, mouseup

Sergey Konstantinov
28 января 2016, 02:54
Если вам нужно отличать действия пользователя от остальных способов изменить положение карты - в логике работы вашего приложения, скорее всего, ошибка.
Мы сознательно не открываем событий перетаскивания карты именно по этой причине.
Удалённый пользователь
28 января 2016, 02:54

раз уже вы прочитали, то расшифруйте, пожалуйста, что имелось ввиду под "плавным" движением карты?

Sergey Konstantinov
28 января 2016, 02:54
Немоментальные перемещения - инерция драга, масштабирование по колесу и т.п.

Возможно ошибка и есть, я всё ж не гуру. Однако вот у Placemark есть событие drag, т.е. испольльзование этого события логику приложения не нарушает?

Sergey Konstantinov
28 января 2016, 02:54
Нет, не нарушает. Геообъект - это сущность, привязанная к некоторой точке на карте. Его геокоординаты не могут измениться в результате работы каких-то внешних компонент АПИ, а только с явного указания разработчика - посредством выставления draggable или явного перезадания координат.

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

Соответственно, попытки разделить "программное" и "пользовательское" изменение положения карты некорректны. Если пользователь вбил "Москва" в поиск - это программное изменение центра карты? Клик по кластеру? Изменение размеров окна браузера?

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

У меня есть Placemark на карте. С течением времени его геокоординаты могут изменяться. По-умолчанию карта должна центрироваться на этом Placemark'е, однако, если пользователь захотел посмотретьна карте другое место, и решил карту "потаскать", центрирование на Placemark нужно отключить. Вот поэтому у меня и возник такой вопрос

Sergey Konstantinov
28 января 2016, 02:54
А в каких ситуациях карта двигается программно?

Как только координаты Placemark'а поменялись, вызываю panTo() либо setCenter() чтобы отцентрировать (если нужно) на нём карту (это я и имел ввиду программно).

Sergey Konstantinov
28 января 2016, 02:54
Тогда как-то так:
// pm - ваш placemark
map.events.add('boundschange', function (e) {
   var newCenter = e.get('newCenter'),
         pmPosition = pm.geometry.getCoordinates();
   if (Math.abs(pmPosition[0] - newCenter[0]) > 1e-6 || Math.abs(pmPosition[1] - newCenter[1]) > 1e-6) {
      // Снимаем слежение за координатами метки
  }
});
Иными словами, если в результате чего-то центр карты стал отличаться от позиции метки - считать это "действием пользователя".

Спасибо!

А имеет ли право на жизнь такой вариант?

function onMoveMouse(){

//снимаем слежение за координатами метки

map.events.remove('mousemove', onMoveMouse);

}

map.events.add('mousedown', function(){

map.events.add('mousemove', onMoveMouse);

}) ;

map.events.add('mouseup', function(){

map.events.remove('mousemove', onMoveMouse);

}) ;

Sergey Konstantinov
28 января 2016, 02:54
Смотря чего вы хотите добиться.
Таким образом, например, зум колесом не будет отключать автоцентрирование. Вы точно этого хотите?

Да. Я хочу отключать автоцентрирование только по "тасканию" карты мышкой

Sergey Konstantinov
28 января 2016, 02:54
Тогда ваш код правильный. Я бы только посоветовал ещё пользоваться методом once.

Прошу вас помочь и мне с решением проблемы.

Логика приложения такова:
есть функция загрузки объектов на карту (ajax запрос на сервер).После загрузки объектов вызываем ymaps.util.bounds.getCenterAndZoom() чтобы все объекты попали в область карты.

Эта функция вызывается в двух случаях:
1. при инициализации карты ymap
2. по событию actionend. 


Проблема в том, что после первичной загрузки объектов на карту чаще всего срабатывает зумирование, поэтому выстреливает событие actionend из-за чего функция загрузки объектов на карту вызывается повторно.

Как исключить повторный вызов? Все работает асинхронно, конечно же. Если включать синхронность появляются дикие тормоза и очереди.

Sergey Konstantinov
28 января 2016, 02:54
Проще всего воспользоваться готовым инструментом.
http://habrahabr.ru/company/yandex/blog/243665/

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

Определить сначала координаты с зумом сложно да и не нужно - это задача клиента (ymaps). Сервер всего-нишь возвращает набор меток с координатами.
Попробуем разобраться с ObjectManager, но решение, прямо скажем, не из коробки.
А задача-то тривиальная. 

Логика такова, что при загрузке карты мы получаем некий набор меток и важно спозиционировать карту так, чтобы все полученные метки влезли на карту. Последующее поведение меняется: мы вручную меняем масштаб и область карты и грузим с сервера на нее метки (только те, что попадают в видимую область и не более того).