Анимации и вибрации: как задизайнить фидбэк слайдера оплаты

69c42845564dee07495144b2c60a650d.png

Кофе — продукт, который можно покупать и пить хоть несколько раз в день. Заказ в приложении Дринкита должен быть супер-пупер быстрым. В идеале, чтобы можно было даже не запускать его, а заказывать из виджета на домашнем экране.

Год назад для упрощения оплаты мы отказались от лишней навигации и вынесли кнопку оплаты прямо в меню. Кнопка внизу экрана позволяла как перейти в корзину, так и сразу начать оплату.

9a87235350a9cf8a363c5946b729a400.jpeg

Но у такой кнопки оказалось несколько проблем:

  • непонятно, что можно на неё нажать — в реальности люди делают это в половине случаев. Но за последние 3 месяца видно, что гости к ней привыкают и пользуются всё чаще;

    236dea9d04835237f90396b0278607c7.png
  • обучаемость не сильно зависит от частоты заказов: есть люди, которые и на двадцатый раз оплачивают из корзины. Тем не менее, в среднем после третьего заказа чаще платят из меню;

    »
  • можно нажать случайно, что создаёт неожиданный заказ;

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

Решение

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

За основу можно взять Slide to Unlock из самого первого айфона, докрутить под себя и дать необычный опыт заказа в приложении.

Как разблокировался первый айфон:

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

Чтобы всё работало хорошо, мы опираемся на три принципа:

  • понятные состояния,

  • приятные анимации,

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

Все состояния слайдера

Для начала разберёмся с «конечными» положениями слайдера, которые обслуживают запрос в бэкенде:

  • ждёт, когда свайпнут;

  • идет оплата;

  • если оплата прошла успешно, то кнопка исчезает;

  • или оплата зафейлилась.

Анимации

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

Анимация учит

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

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

  • при тапе на кнопку делаем то же самое. Так переучим старых пользователей: теперь нужно не тапать, а тащить;

  • время от времени ещё раз мигаем анимацией, чтобы привлечь внимание, если пропустили на прошлых этапах.

Скрашивает ожидание

Обычно оплата проходит от 2 до 6 секунд — за это время проиграем анимацию ожидания пару раз.

Даёт фидбэк

Оплата не прошла — «трясём» кнопкой и даём время прочитать.

Метафора натяжения

Когда мы сделали первый прототип, поняли, что просто ездить кнопкой — скучно. Чтобы сделать оплату запоминающейся, нужна какая-то метафора: она поможет объяснить все следующие эффекты.

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

727ef55ddcf64ec7c3b8db7a7aaeccc1.jpg

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

В итоге человеку надо не перетащить кнопку, а заполнить всю шахту лифта.

c68c3859d294ad2cb1fac58383d41a17.gif

Натяжение, интерактивность и velocity

Дальше будет про интерактивность, поэтому лучше попробовать самим. Скачайте приложение, авторизуйтесь, выберите в корзине «новую карту» и попробуйте посвайпать. Зафейленные состояния можно получить в авиарежиме. Если вдруг нечаянно оплатили, то отменить можно из экрана заказа.

С процессом натяжения посложнее:

  • в разное время натягивания видны разные данные;

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

  • протащить слайдер через весь экран достаточно сложно и не очень удобно.

Незавершение

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

С резиновостью важно не переборщить. Мне нравится такой подход: все действия, которые инициировал компьютер, должны быть плавными: машина расчётлива, делает точно. А вот всё, что сделал человек, имеет инерцию и может иметь резиновый фидбэк.

Завершение

Apple продвигает Fluid интерфейсы. Если совсем кратко, то анимации в интерфейсе должны быть:

  • естественными,

  • прерываемыми,

  • «продолжающими» движение, т.е. учитывающими скорость

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

public extension CGFloat { // Velocity value from UIPanGestureRecognizer
    func projectedOffset(decelerationRate: UIScrollView.DecelerationRate) -> CGFloat {
        // Magic formula from WWDC
        let multiplier = 1 / (1 - decelerationRate.rawValue) / 1000
        return self * multiplier
    }
}

Во время разработки мы написали код неправильно, поэтому при быстром свайпе кнопка не растягивалась до конца сама, а будто бы пролетала, нерастянувшись. Эффект нам понравился, и мы решили так и оставить. Получилось две анимации: если натягивать до конца, то шкала будет заполняться, а если свайпнуть быстро — кнопка сама долетит.

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

Вибрации

Эмоции можно подкрепить тактильно, для этого в айфоне встроен специальный haptic-мотор. Это не обычная вибрация от крутящегося элемента: haptic может начать вибрировать моментально, быстро закончить и вибрировать по-разному, поэтому им можно сделать разные эффекты.

Есть стандартные и полностью настраиваемые вибрации.

Стандартные вибрации

  • .selection — «тюк», очень слабый, как у барабана, который настраивает время в будильнике. Нам применить его негде.

  • .warning — «ту-ду», два небольших толчка. Подойдут, чтобы закрепить завершение свайпа и начать оплату.

  • .success — «та-дам», как при оплате Face Id. Подойдёт для подтверждения оплаты, когда ожидание уже закончилось.

  • .error —«та-да-да», несколько сильных толчков. Используем, если оплата не прошла.

Для остального можно сделать собственную вибрацию.

Настраиваемые вибрации

Для кастомных вибраций есть несколько параметров, которые можно настроить:

  • тип: продолжительная (continuous) или короткий щелчок (transient). Для продолжительной нужно указать длительность;

  • сила (intensity) и острота (sharpness);

  • время атаки и затухания, за которое возрастает или слабеет сила вибрации.

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

Когда-то я написал приложение Haptic Composer, которое позволяет пощупать разные вибрации. Скриншоты из приложения мы прямо так и перенесли в макет:

33441239a275da5c456e8bd22a7a6586.png

Для одиночных действий можно настроить паттерн, как песню из нот, и проиграть мелодию в нужный момент. Haptic Composer так не умеет, и мы переключились в Hapticly, который позволяет генерировать несколько вибраций подряд.

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

Интерактивные вибрации

Для интерактивных элементов всё сложнее, потому что уже нельзя просто задать паттерн, нужно реагировать не действие. У нас получились такие правила:

  • при натягивании мы играем вибрации продолжительностью по 0.1 секунды, но они сливаются и ощущается резинка. Сила вибрации зависит от дальности натяжения: чем дальше, тем сильнее слайдер «сопротивляется»;

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

static func sliderCancelled(progress: Float) -> CHHapticPattern {
    var events: [CHHapticEvent] = [.transient(intesity: progress, sharpness: 0.8)]
    
    if progress > 0.3 {
        events.append(.transient(intesity: 0.5, sharpness: 0.6, relativeTime: 0.1))
    }
    
    if progress > 0.5 {
        events.append(.transient(intesity: 0.2, sharpness: 0.6, relativeTime: 0.2))
    }
    
    return .pattern(events: events)
}

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

В CoreHaptics есть ещё более точное управление параметрами через кривые, а ещё можно читать их из файла с расширением .ahap. Я бы посмотрел на фильм с такой «вибродорожкой»!

Контекст для слайдера

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

Как товар добавляется в корзину

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

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

После оплаты может открыться экран ввода карты

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

Интересно, пройдёт ли перетаскивание кнопки Apple Pay ревью у Apple, но сейчас мы это не сможем узнать.

Оплата занимает время

В среднем оплата проходит около 2–6 секунд, анимация ожидания сыграет в это время несколько раз. Мы решили не добавлять вибрации для этих анимаций: человек может опустить руку в ожидании, тогда мы привлечём его внимание вибрацией после успешной оплаты или ошибке. Тип вибрации достаточно красноречиво опишет результат, даже если анимацию завершения пользователь увидеть не успеет.

4d9864e0a6a529e49e4b2e1089a51058.jpeg

После оплаты переходим в созданный заказ

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

В этом сценарии есть что улучшить: от скрытия кнопки до показать проходит секунда. Пуш сверху сглаживает ожидание, но отвлекает своим местоположением. Должно быть проще: кнопка скрывается вместе с появлением заказа. Обязательно улучшим.

Доступность

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

Визуальная доступность

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

Первая — уменьшение движения. Люди, которые включили её, хотят, чтобы анимаций было поменьше, потому что это доставляет им дискомфорт или даже может спровоцировать эпилептический припадок. Поддержать просто — проверить значение этой настройки перед анимацией, и если попросили без анимаций, то не включать их. Эта же настройка влияет и на частоту показа анимации: если стандартно мы показываем каждые 5 секунд, то с этой настройкой стоит снизить частоту до 20.

Вторая — предпочтение перекрестным наплывам: все переходы должны быть не сдвигом, а через cross-fade, т.е. появление через изменение прозрачности.

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

Невизуальная доступность

Незрячие пользуются VoiceOver — он озвучивает элементы на экране, а для этого ему нужно текстовое описание всех элементов. Чтобы оно было, нужно разметить UI специальной accessibility-разметкой и спроектировать, какой UX получится в итоге.

  1. Нам нужно название элемента. У нас две кнопки, но главная из них открывает корзину. Так и назовём: «Корзина, кнопка». Обратите внимание, что здесь есть и тип элемента — так человек поймёт, что на неё можно нажать.

  2. У нас есть дополнительная информация о товарах и цене. Добавим их в качестве значения элемента, получится «Корзина, 369 рублей, 3 товара, кнопка».

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

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

Добавить кнопку быстрой оплаты можно двумя путями:

  1. Сделать её просто отдельной кнопкой, но тогда VoiceOver каждый раз будет фокусироваться на ней, это может мешать.

  2. Перенести это в дополнительное действие кнопки перехода в корзину. Это подходит.

В итоге незрячий человек со включенным VoiceOver горизонтальными свайпами дойдёт до этой кнопки, услышит описание «Корзина, 369 рублей, 3 товара, кнопка. Доступны действия» и либо тапнет дважды, чтобы перейти в корзину, либо свайпнет вертикально, чтобы выбрать действие «Оплатить», и уже после этого тапнет дважды.

В этой адаптации есть что улучшать: согласовать множественное число и поправить произношение рубля, но это терпимо. Увы, остальная часть приложения недоступна, но начать можно с любого элемента, а самый первый шаг — начать говорить об этом.

Эффективней всего начать адаптировать элементы с дизайн-системы — так вы получите максимальное влияние на приложение. Если хотите узнать больше про доступность — читайте нашу книгу «Про доступность iOS», прямо сегодня она бесплатная.

Результаты

Провал

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

    4ec07cf447f7b5779ed5d6243c23d0c9.png
  2. Мы обработали ошибки оплаты, но забыли показать ошибки создания заказа, когда какой-то продукт больше нельзя показать. Решили в случае таких ошибок открывать экран корзины — там можно удалить продукт или поменять его состав. Такие проблемы бывают редко, всего в 1.5% заказов, но со следующим релизом мы это улучшили.

    4c2457c1264ffa7b347256d87d57388e.png
  3. В проекте ещё не была готова аналитика на таком уровне, чтобы эффективно замерить слайдер А/Б-тестом. Возможно (если не забудем и будет время), мы сделаем деградирующий тест, чтобы понять эффективность слайдера.

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

При запуске было несколько ошибок, но мы их смогли поправить в течении первых двух недель после запуска. Релиз — лишь часть успеха, остальное сделает аналитика, обратная связь и персональная гемба!

Успех

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

Если понравилась статья и хочешь больше узнать о разработке приложений Dodo Brands, подписывайся на наш канал Dodo Mobile.

Если ты дизайнер и тоже хочешь развивать наши приложения — приходи, у нас есть открытые вакансии для синьор-дизайнеров. А если хочется узнать больше про необычные интерфейсы, то можно почитать, как сделана пицца из половинок.

© Habrahabr.ru