В данный момент я работаю над дизайн-системой крупного SDUI-проекта и в этой статье хочу поделиться своим опытом реализации хаптика в наших приложениях: разобрать проблемы, с которыми вы, возможно, столкнётесь, и прийти к консистентному решению на трёх платформах: iOS, Android и мобильном вебе.

В этой статье я пошагово разберу путь от хаоса («каждая платформа делает что-то своё») к единой системе хаптик-пресетов, которую дизайнер настраивает в Figma, а разработчик получает в JSON.

Но для начала давайте коротко проговорим, что такое хаптик.

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

Для современных приложений это уже давно стало нормой, а для пользователя — неотъемлемой частью привычного опыта. Но когда начинаешь копать, выясняется, что у платформ совершенно разные подходы к тактильной отдаче, а готового кроссплатформенного решения нет.

Где и зачем нужен хаптик

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

Примеры хаптиков

Тап / нажатие — кнопки, ячейки, баннеры. Хаптик здесь подтверждает действие и создаёт ощущение «физической» кнопки. Пользователь не гадает, нажал он или нет — он это чувствует. Например, отправка сообщения в Telegram или лайк в Instagram.

Свайпы — жесты по карточкам, шторкам, табам. Тактильный сигнал обозначает достижение порога: «ещё немного — и карточка улетит». Помогает управлять жестом, не глядя на экран. Классический пример — свайп в Tinder.

Драг / перетаскивание — сортировка списков, перемещение элементов. Хаптик создаёт иллюзию веса и сопротивления, подтверждает фиксацию объекта на новом месте. Например, перетаскивание виджетов на рабочем столе iOS.

Ошибки и ограничения — попытка ввести недопустимое значение, невалидная форма. Мгновенная обратная связь без чтения текста — пользователь понимает, что что-то пошло не так, ещё до того, как увидел сообщение. Паттерн универсален и снижает когнитивную нагрузку.

Успех / подтверждение — завершение оплаты, отправка формы, достижение в игре. Эмоциональное подкрепление и чёткая точка завершения действия.

Скролл и пределы контента — bounce-эффект при достижении конца списка. Пользователь чувствует границу, даже не глядя на экран.

Лонгтапы — вызов контекстного меню, раскрытие дополнительных действий. Хаптик подтверждает, что долгое нажатие зарегистрировано.

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

Анимации и переходы — делают анимацию «осязаемой», подсвечивают ключевые точки. Часто встречается в анимациях онбординга.

Что предлагают платформы

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

У Google нет единой философии использования тактильной отдачи. Есть набор констант (KEYBOARD_TAP, LONG_PRESS, CLOCK_TICK и т.д.), но за ними не стоит смысловая модель — это скорее перечисление аппаратных возможностей.

У Apple — другая история. Хаптики разделены на три семантических типа, и различаются они не силой удара, а смыслом события, которое обозначают:

  • Impact — физическое взаимодействие с элементом (тап, свайп, фиксация)
  • Selection — переход между дискретными значениями (пикер, сегменты)
  • Notification — результат события, не требующий касания (успех, ошибка, предупреждение)

Именно эту семантику мы взяли за основу. Далее я опираюсь на нейминг Apple — это будет важно при мэтчинге между платформами.

Impact — физическое взаимодействие с элементом

Хаптик типа Impact используется в моменты физического взаимодействия элементов интерфейса — например, когда пользователь тапает на эллемент интерфейса, карточка фиксируется на позиции или жест достигает порога действия. Такой отклик имитирует ощущение контакта и делает поведение интерфейса более материальным.

Для этого используются уже готовые преднастроенные паттерны:

Light — Кратковременный низкоинтенсивный импульс.

Medium — Кратковременный импульс средней интенсивности.

Heavy — Кратковременный импульс высокой интенсивности.

Soft — Импульс с пониженной амплитудой и сглаженным фронтом.

Rigid — Импульс с высокой амплитудой и резким фронтом.

Selection — изменение текущего значения

Хаптик типа Selection используется при переходе между дискретными значениями — например, при прокрутке пикера или переключении сегментов. Короткий тактильный «тик» сопровождает каждую смену выбранного варианта и помогает пользователю ощущать шаги интерфейса.

Apple предлагает один преднастроенный паттерн:

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

Notification — результат события

Хаптик типа Notification применяется для обозначения результата события — успеха, предупреждения или ошибки. Такой отклик усиливает статус сообщения и помогает пользователю быстрее распознать характер происходящего. Не требует физического взаимодействия пользователя с интерфейсом.

Apple предлагает три преднастроенных паттерна:

Success — Последовательность из 2-х импульсов, сигнализирующая об успешном завершении операции.

Warning — Последовательность из 2-х импульсов средней интенсивности, обозначающая предупреждение.

Error — Последовательность из 4-х импульсов с акцентированной интенсивностью, обозначающая ошибку.

Кастомный хаптик

Для нашего приложения нам также понадобился кастомный хаптик с гибкой настройкой — например, для сложных Lottie-анимаций.

Важная оговорка: тактильная отдача воспроизводится вибромотором устройства. У Apple вибромоторы стандартизированы, а на Android-устройствах можно встретить совершенно разные моторы, часть которых может не поддерживать параметр интенсивности. При тестировании лучше использовать устройство, в котором вы уверены — мы тестировали на OnePlus 15, и результаты с iPhone совпали практически идеально.

Для упрощения JSON-схемы (что важно для SDUI-приложения) мы сократили параметры вибромотора до трёх основных:

  • Delay — задержка перед началом вибрации в миллисекундах (отсчитывается от нуля)
  • Duration — длительность вибрации в миллисекундах
  • Intensity — интенсивность вибрации от 0 до 1

Нейминг выбран не случайно — мы ориентировались на готовое решение для мобильного веба.

Мэтчим платформы

Изначально я планировал сопоставить пресеты Apple напрямую с пресетами Google:

Однако при тестировании стало понятно, что прямой маппинг не работает: Google-константы подбирались по формальному сходству названий, но тактильные ощущения на устройстве не совпадали — интенсивность, длительность и «характер» вибрации отличались настолько, что пользователь получал бы принципиально разный опыт на iOS и Android. Поэтому мы решили переписать пресеты для Android на основе наших кастомных параметров.

Apple не раскрывает точные настройки своих пресетов, но дает понятную графику, которую несложно перевести в численные значения относительно наших параметров (Delay, Duration, Intensity).

В итоге получились следующие значения:

Impact-пресеты

Selection

Notification-пресеты (составные)

Success (2 импульса):

Warning (2 импульса):

Error (4 импульса):

Мэтчим код с компонентом в Figma

Мне кажется важным, чтобы структура компонентов в коде и Figma была максимально синхронизирована. Это особенно полезно, если вы хотите оптимизировать взаимодействие «дизайнер — разработчик», например, с помощью плагинов, которые умеют читать компоненты и конвертировать их в JSON-схему.

У нас в коде структура Haptic представляет собой OneOf-параметр, состоящий из набора пресетов и кастомного хаптика. В Figma я реализовал это через swap instance-параметр, где дизайнер выбирает тип хаптика.

Если выбран пресет — всё просто. Если кастом — появляются дополнительные параметры:

Patterns: Array { Pattern }

Массив хаптиков для создания более сложной тактильной отдачи. В Figma реализован через варианты и выглядит так:

И три параметра для каждого паттерна из массива, которые я реализовал через скрытые параметры Text:

  • Delay: Integer — задержка перед началом вибрации
  • Duration: Integer — длительность вибрации
  • Intensity: Number — интенсивность от 0 до 1

В Figma выглядит так:

Итого

Мы получили единую систему хаптик-пресетов, которая:

  • Семантична — основана на смысловой модели Apple (Impact / Selection / Notification), а не на аппаратных константах
  • Кроссплатформенна — одинаково ощущается на iOS и Android благодаря кастомным параметрам вместо прямого маппинга платформенных API
  • Расширяема — кастомный хаптик через Delay / Duration / Intensity покрывает нестандартные сценарии (Lottie-анимации, игровые механики)
  • Синхронизирована с дизайном — компонент в Figma зеркалит структуру кода и конвертируется в JSON

Из ограничений: поддержка хаптика в мобильных браузерах пока значительно уступает нативным платформам. Для веба мы используем упрощенный набор паттернов из тех же параметров, но без Intensity — это компромисс, а не полноценный паритет с нативными платформами, но общая структура пресетов позволяет хотя бы сохранить консистентный нейминг и логику.

Приятной тактильной отдачи!


Хаптик. Как сделать консистентное кроссплатформенное решение и помирить код с Figma was originally published in Дизайн-кабак on Medium, where people are continuing the conversation by highlighting and responding to this story.

©


Смотрите также/You may also like