- PVSM.RU - https://www.pvsm.ru -
Современный мир диктует разработчикам и дизайнерам довольно высокие стандарты качества и удобства использования веб-приложений. Как правило, хорошее впечатление о приложении складывается из множества мелочей, которые должны гармонично сочетаться между собой. Одной из таких мелочей может являться инерционное движение “драгабельных” (перетаскиваемых) объектов на странице — об этом мы и поговорим в рамках сегодняшней небольшой статьи. Фича особенно актуальна при взаимодействии пользователя с приложением посредством тач-устройств, так как размер экранов таких устройств ограничен, и передвигать объект из одной точки в другую хочется одним “легким движением руки”, а не многократными касаниями экрана.
Подобным вопросом мы когда-то задались в рамках разработки API карт 2GIS [1], а сегодня решили поделиться нашим скромным опытом.
Прежде чем рассматривать детали реализации инерции, давайте взглянем на уже готовые примеры:
Хорошо, теперь к делу.
В качестве тестового примера добавим инерционное перемещение к одному из картографических API, у которого еще нет такой фичи. Таким образом мы: а) чему-то научимся; б) нанесем кому-то необратимую пользу.
Давайте искать столь “обделенное” API. Bing [5], Google [6]? Нет, у этих ребят с перетаскиванием карты все в порядке. Посмотрим, как обстоят дела у OpenLayers 3 [7]. Да, наш “пациент”, над ним и будем ставить эксперименты.
Несмотря на молодость “подопытного”, установка трудностей не вызвала, все как в документации [8]:
Исходный код всех html, js и css файлов примеров можно найти в папке ol3/examples.
На самом деле, все довольно просто.
Подготовка к инерционному движению:
Метод inertiaMove вызывается раз в определенный период (каждых 16 мс., например). В этом методе мы:
“Экстренная” остановка перетаскивания. Карта должна принудительно перестать двигаться в двух случаях:
Так как OpenLayers 3 сделан на основе Closure library [9], будем писать код по его правилам.
Взглянув на файловую структуру, мы увидим, что в каталоге interactions находятся все объекты, которые отвечают за взаимодействие с картой. Среди них есть объект ol.interaction.DragPan [10], отвечающий за перетаскивание, создадим и отнаследуем от него наш ol.interaction.DragPanInertia [11] и реализуем в нем инерционное движение карты.
Также для удобства была добавлена [12] реализация polyfill-а для метода requestAnimationFrame [13] от Erik Möller [14].
Что касается принудительной остановки движения карты, делается это весьма простой подпиской на соответствующие события:
var eventType = ol.BrowserFeature.HAS_TOUCH ? goog.events.EventType.TOUCHEND : goog.events.EventType.MOUSEDOWN;
// mouse down
goog.events.listen(this._map.getViewport(), eventType, this.stopInertiaMove, false, this);
// zoom changed
goog.events.listen(this._map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION), this.stopInertiaMove, false, this);
Для того, чтобы карта начала использовать реализованные нами объекты, их необходимо зарегистрировать в методе createInteractions [15] объекта ol.Map.
Сначала подключаем нашу реализацию, заменив
goog.require('ol.interaction.DragPan');
на
goog.require('ol.interaction.DragPanInertia');
А потом строку
interactions.push(new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys));
заменяем на
interactions.push(new ol.interaction.DragPanInertia(ol.interaction.condition.noModifierKeys));
Как вы уже наверное заметили, реализованный нами код лежит на github-е [16], а, благодаря github pages [17], вы можете посмотреть в действии [18] пример карты с инерцией при передвижении. Пример лучше всего смотреть в Google Chrome, так как под различные браузеры и устройства он не оптимизировался, это не является основной целью статьи. Что же касается самого OpenLayers 3, то библиотека находится в стадии активной разработки и использовать ее в “боевых” приложениях пока не стоит (имеются проблемы при работе с тач-устройствами [19], а также со стабильностью самого API [20]). Тем не менее, пожелаем разработчикам выдержки, вдохновения и хороших pull request-ов в столь полезный для пользователей проект.
Автор: AndreyGeonya
Источник [21]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/25023
Ссылки в тексте:
[1] API карт 2GIS: http://api.2gis.ru/about/features/#maps
[2] инерционный скролл: http://cubiq.org/dropbox/iscroll4/examples/simple/
[3] инерционное движение карусели фотографий: http://www.annefrank.org/en/Subsites/Timeline/#!/en/Subsites/Timeline/
[4] инерционное перемещение карты 2GIS: http://maps.api.2gis.ru/
[5] Bing: http://www.bing.com/maps/
[6] Google: https://maps.google.com.ua/
[7] OpenLayers 3: https://github.com/openlayers/ol3
[8] документации: https://github.com/AndreyGeonya/ol3#run-the-examples-in-debug-mode
[9] Closure library: https://developers.google.com/closure/library/?hl=ru
[10] ol.interaction.DragPan: https://github.com/AndreyGeonya/ol3/blob/master/src/ol/interaction/dragpaninteraction.js
[11] ol.interaction.DragPanInertia: https://github.com/AndreyGeonya/ol3/blob/master/src/ol/interaction/dragpaninertiainteraction.js
[12] была добавлена: https://github.com/AndreyGeonya/ol3/blob/master/src/ol/polyfill/requestanimationframepolyfill.js
[13] requestAnimationFrame: https://developer.mozilla.org/en-US/docs/DOM/window.requestAnimationFrame
[14] Erik Möller: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
[15] createInteractions: https://github.com/AndreyGeonya/ol3/blob/master/src/ol/map.js#L1083
[16] на github-е: https://github.com/AndreyGeonya/ol3
[17] github pages: http://pages.github.com/
[18] посмотреть в действии: http://andreygeonya.github.com/inertiaDemo/
[19] работе с тач-устройствами: https://github.com/openlayers/ol3/issues/109
[20] стабильностью самого API: https://github.com/openlayers/ol3/pull/96#issuecomment-11949939
[21] Источник: http://habrahabr.ru/post/166061/
Нажмите здесь для печати.