Пользовательский опыт

Пользовательский опыт (User Experience, UX) в картографических веб-приложениях определяется не только качеством визуализации данных, но и удобством взаимодействия с картой. В Mapbox GL JS UX формируется через навигацию, отклик интерфейса, работу с данными, анимации, адаптивность и доступность.

Карта выступает полноценным интерактивным интерфейсом, поэтому проектирование пользовательского опыта требует такого же внимания, как разработка форм, меню или информационных панелей.


Принципы проектирования картографического интерфейса

При создании интерфейсов на основе Mapbox GL JS необходимо учитывать несколько фундаментальных принципов.

Простота взаимодействия

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

  • где находится;
  • какие данные отображаются;
  • как изменить масштаб;
  • каким образом получить дополнительную информацию.

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

Плохой пример:

  • множество кнопок;
  • десятки слоёв, включённых одновременно;
  • перегруженные всплывающие окна.

Хороший пример:

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

Предсказуемость поведения

Каждое действие должно приводить к ожидаемому результату.

Например:

  • колесо мыши увеличивает масштаб;
  • двойной щелчок приближает карту;
  • перетаскивание перемещает область просмотра;
  • клик по объекту показывает детали.

Нестандартное поведение может дезориентировать пользователей.


Визуальная иерархия

На карте всегда должны выделяться наиболее важные объекты.

Для этого используются:

  • размер символов;
  • цветовая контрастность;
  • прозрачность;
  • порядок отображения слоёв.

Пример:

paint: {
    "circle-radius": 8,
    "circle-color": "#ff0000"
}

Крупные красные точки будут восприниматься как объекты первого уровня важности.


Навигация по карте

Навигация является одним из важнейших элементов UX.

Стандартные элементы управления

Mapbox GL JS предоставляет встроенные контролы навигации.

map.addControl(
    new mapboxgl.NavigationControl()
);

Добавляются кнопки:

  • увеличение масштаба;
  • уменьшение масштаба;
  • сброс вращения карты.

Это снижает порог входа для новых пользователей.


Ограничение диапазона масштабирования

Слишком сильное увеличение или уменьшение часто приводит к потере контекста.

const map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/streets-v12",
    minZoom: 4,
    maxZoom: 16
});

Преимущества:

  • предотвращение отображения бесполезных уровней;
  • повышение производительности;
  • упрощение навигации.

Ограничение области карты

Если приложение работает только в определённом регионе, полезно ограничить перемещение.

map.setMaxBounds([
    [30, 40],
    [50, 60]
]);

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


Геолокация пользователя

Определение текущего местоположения существенно улучшает пользовательский опыт.

Контрол геолокации

map.addControl(
    new mapboxgl.GeolocateControl({
        positionOptions: {
            enableHighAccuracy: true
        },
        trackUserLocation: true
    })
);

Возможности:

  • определение текущего положения;
  • автоматическое отслеживание перемещения;
  • быстрое центрирование карты.

Отображение текущего местоположения

Пользователь должен видеть своё положение максимально очевидно.

Распространённые подходы:

  • синяя точка;
  • круг точности GPS;
  • индикатор направления движения.

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


Работа со всплывающими окнами

Popup является одним из основных способов отображения информации.

Создание всплывающего окна

new mapboxgl.Popup()
    .setLngLat([37.6173, 55.7558])
    .setHTML("<h3>Москва</h3>")
    .addTo(map);

Минимизация объёма информации

Всплывающее окно не должно превращаться в полноценную страницу.

Рекомендуется показывать:

  • название объекта;
  • ключевые показатели;
  • краткое описание;
  • ссылку на подробности.

Плохо:

<div>
    20 абзацев текста...
</div>

Хорошо:

<div>
    <h3>Магазин</h3>
    <p>Открыт до 22:00</p>
</div>

Автоматическое закрытие окон

Большое количество открытых Popup перегружает интерфейс.

Практика:

let currentPopup;

map.on("click", e => {

    if (currentPopup) {
        currentPopup.remove();
    }

    currentPopup = new mapboxgl.Popup()
        .setLngLat(e.lngLat)
        .setText("Информация")
        .addTo(map);
});

На экране остаётся только одно окно.


Анимации и плавность интерфейса

Плавные переходы значительно улучшают восприятие карты.

FlyTo

Метод создаёт анимированный перелёт к указанной точке.

map.flyTo({
    center: [37.6173, 55.7558],
    zoom: 12,
    duration: 3000
});

Преимущества:

  • сохранение пространственного контекста;
  • понятное перемещение между областями;
  • улучшение визуального восприятия.

EaseTo

Для более спокойной анимации применяется:

map.easeTo({
    center: [37.6173, 55.7558],
    zoom: 12
});

Такой переход выглядит мягче и менее агрессивно.


Когда анимации вредят UX

Следует избегать:

  • длительных перелётов;
  • постоянных автоматических перемещений;
  • чрезмерного количества эффектов.

Карта должна реагировать быстро и предсказуемо.


Обратная связь интерфейса

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

Изменение курсора

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

map.on("mouseenter", "places", () => {
    map.getCanvas().style.cursor = "pointer";
});

map.on("mouseleave", "places", () => {
    map.getCanvas().style.cursor = "";
});

Это сигнализирует о возможности взаимодействия.


Подсветка объектов

Объект может выделяться при наведении.

map.setPaintProperty(
    "places",
    "circle-color",
    "#ff0000"
);

Пользователь сразу понимает, какой элемент активен.


Состояния загрузки

При длительном получении данных желательно показывать индикатор загрузки.

map.on("dataloading", () => {
    loader.style.display = "block";
});

map.on("idle", () => {
    loader.style.display = "none";
});

Это предотвращает ощущение зависания приложения.


Работа с большими объёмами данных

UX напрямую зависит от производительности.

Кластеризация точек

Тысячи маркеров могут сделать карту нечитаемой.

Mapbox поддерживает кластеризацию GeoJSON.

map.addSource("places", {
    type: "geojson",
    data: data,
    cluster: true,
    clusterRadius: 50
});

Преимущества:

  • уменьшение визуального шума;
  • повышение скорости рендеринга;
  • упрощение анализа данных.

Постепенное раскрытие информации

На малых масштабах показываются агрегированные данные.

При увеличении масштаба:

  • появляются отдельные объекты;
  • отображаются дополнительные атрибуты;
  • становятся доступны детальные действия.

Такой подход называется Progressive Disclosure.


Адаптивность интерфейса

Картографические приложения часто используются на смартфонах.

Изменение расположения контролов

Для мобильных устройств полезно менять положение элементов управления.

map.addControl(
    new mapboxgl.NavigationControl(),
    "bottom-right"
);

Часто это удобнее стандартного размещения сверху.


Размер интерактивных элементов

Слишком маленькие объекты неудобны для касания.

Рекомендуемые размеры:

  • кнопки от 44×44 пикселей;
  • маркеры достаточного диаметра;
  • крупные зоны нажатия.

Учет ориентации экрана

На вертикальных экранах пространство ограничено.

Полезные практики:

  • скрытие второстепенных панелей;
  • сворачиваемые меню;
  • полноэкранная карта.

Доступность (Accessibility)

Качественный UX невозможен без доступности.

Контрастность цветов

Низкий контраст ухудшает читаемость.

Желательно избегать сочетаний:

  • светло-серый на белом;
  • зелёный на красном;
  • жёлтый на белом.

Лучше использовать отчётливо различимые цвета.


Независимость от цвета

Информация не должна передаваться исключительно через цвет.

Плохо:

  • красный — авария;
  • зелёный — нормально.

Хорошо:

  • цвет;
  • форма;
  • иконка;
  • подпись.

Клавиатурная навигация

Некоторые пользователи взаимодействуют без мыши.

Интерфейс вокруг карты должен поддерживать:

  • Tab;
  • Enter;
  • Escape;
  • стрелки.

Информационные панели

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

Синхронизация карты и списка

При выборе элемента списка карта должна автоматически центрироваться.

map.flyTo({
    center: feature.geometry.coordinates,
    zoom: 15
});

Двустороннее взаимодействие

Связь должна работать в обе стороны.

Клик по карте:

  • выделяет объект в списке.

Клик по списку:

  • выделяет объект на карте.

Такой подход создаёт целостный пользовательский опыт.


Проектирование сценариев взаимодействия

Каждое действие пользователя должно быть частью продуманного сценария.

Типичный сценарий поиска объекта:

  1. Открытие карты.
  2. Определение местоположения.
  3. Ввод поискового запроса.
  4. Получение результатов.
  5. Выбор объекта.
  6. Просмотр подробной информации.
  7. Построение маршрута.

На каждом этапе необходимо минимизировать количество действий и снижать когнитивную нагрузку.


Персонализация картографического интерфейса

Современные приложения часто адаптируют карту под конкретного пользователя.

Примеры:

  • сохранение последнего положения карты;
  • запоминание масштаба;
  • сохранение активных слоёв;
  • хранение пользовательских фильтров.
map.on("moveend", () => {
    localStorage.setItem(
        "center",
        JSON.stringify(map.getCenter())
    );
});

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


Метрики оценки пользовательского опыта

Для оценки эффективности интерфейса анализируются:

  • время поиска объекта;
  • количество кликов до достижения цели;
  • частота использования элементов управления;
  • процент успешных сценариев;
  • глубина взаимодействия с картой.

Дополнительно могут использоваться события Mapbox GL JS:

map.on("click", e => {
    analytics.track("map_click", {
        lng: e.lngLat.lng,
        lat: e.lngLat.lat
    });
});

Сбор подобных данных позволяет выявлять проблемные участки интерфейса и улучшать пользовательский опыт на основе реального поведения пользователей.