Этот пост был изначально написан Дэниелом Вонгом
Мобильные веб-приложения прошли долгий путь от своих неуклюжих, урезанных предков эпохи до появления смартфона. Адаптивный дизайн и специфичные для мобильных устройств взаимодействия, такие как прикосновения и проводящие события, начали устранять разрыв между мобильными веб-приложениями и нативными приложениями для смартфонов. Поэтому неудивительно, что при работе с мобильным веб-приложением нам часто приходится стремиться не только к функциональному равенству с соответствующим родным приложением, но и к пользовательскому интерфейсу.
Хотя с самого начала можно было бы привести множество аргументов против этого подхода, в недавнем проекте мобильного веб-приложения нам было любопытно посмотреть, как далеко мы можем продвинуться, когда нам поручено следовать нативному идеалу.
Четность макета страниц достаточно проста, но опыт работы с пользовательским интерфейсом гораздо больше, чем просто макет. Все, казалось бы, незначительные вещи на периферии — переходы страниц, модальные диалоговые окна, теперь повсеместная левая скользящая панель навигации — имеют решающее значение. Тем не менее, был один элемент, который мы не ожидали вызвать каких-либо проблем, особенно учитывая, насколько широко он используется — скромный аккордеон.
Проблема с аккордеонами
Для тех, кто немного сомневается в том, что такое аккордеон: это компонент пользовательского интерфейса, состоящий из нескольких разделов, каждый из которых можно открывать и закрывать для отображения и скрытия контента. Вот пример аккордеона в действии:
Открытие и закрытие аккордеонов не проблема. Анимация этих переходов при постепенном раскрытии внутреннего содержания — это отдельная история. В нашей первоначальной реализации мы обнаружили, что производительность при открытии аккордеона на iPhone5 и Samsung Galaxy S4 варьировалась от средней до шокирующе неприемлемой. То, что должно было быть плавной анимацией сползания вниз, было слегка запоздалым на iPhone и полным провалом на S4 — вы едва могли сказать, что он вообще оживлялся между закрытым и открытым состояниями.
К этому моменту мы уже внедрили страницы, скользящие слева и справа с шелковистой плавностью — как это может быть иначе? Проблема заключается в том, как страница реагирует на открытие аккордеона.
Скользящие переходы использовали аппаратное ускорение CSS3 на мобильных устройствах. Поскольку эти переходы просто сдвинули одну страницу вправо, а другую — на свое место, компоновка обеих страниц не изменилась, что достаточно просто для мобильного устройства.
Однако, когда открывается аккордеон, макет страницы необходимо пересчитать в результате изменения высоты. Следовательно, он не получает аппаратного ускорения. Насколько дорог этот пересчет, зависит от множества факторов, но наиболее широко он относится к тому, насколько сложен DOM. По мере того, как высота содержания аккордеона увеличивается постепенно, это событие повторения повторяется снова и снова, и в конечном итоге убивает производительность анимации.
В то время как настольные компьютеры обычно имеют вычислительную мощность, чтобы скрыть эту проблему, это очевидно на смартфоне.
Выставка
Давайте начнем с наивной jQuery-реализации аккордеона. Источник выглядит так:
</pre> <div class="accordion" id="accordion1"> <div class="header">Header 1</div> <div class="content">Content</div> </div> <pre>
$(document).ready(function () { $('.header').click(function (e) { // select the content div var $content = $(e.currentTarget).next(); if (!$content.is(':visible')) { $content.slideDown(); } else { $content.slideUp(); } }); });
(Вы можете найти JSFiddle здесь )
Это настолько просто, насколько это возможно, и на самом деле получает шанс хорошо работать, поскольку в нем мало беспорядка в DOM. Так насколько хорошо он ведет себя на разных устройствах?
Хотя разрыв между производительностью настольных компьютеров и мобильных устройств понятен, разрыв между iPhone 5 и Galaxy S4 сложнее понять. Тем не менее, этот пример использует slideDown()
метод jQuery для открытия аккордеона, программно изменяя высоту указанного элемента div, чтобы открывать и закрывать его. Возможно, мы просто не дали ему возможности использовать какое-либо аппаратное ускорение?
Экспонат Б
Давайте попробуем подход, который использует анимацию CSS3:
.content { overflow:hidden; height: 0px; -webkit-transition: height 0.4s ease; } .content.open { // Ideally this should be set dynamically by the js height: 650px; }
$(document).ready(function () { $('.header').click(function (e) { var $content = $(e.currentTarget).next(); if (!$content.hasClass('open')) { $content.addClass('open'); } else { $content.removeClass('open'); } }); });
(JSFiddle здесь )
Мы видим, что переходы CSS3 применяются через класс; что браузер будет пытаться переместить элемент между двумя состояниями всякий раз, когда класс добавляется в элемент DOM. Если браузер не поддерживает переходы CSS3, он грациозно ухудшается, так что аккордеон просто привязывается к открытой позиции.
Но как это работает?
С точки зрения абсолютных чисел данные о производительности, безусловно, выглядят лучше при таком подходе, но важно еще раз отметить, что этот тест работает в очень минимальном DOM; По нашему опыту, реальная производительность, скорее всего, будет хуже в зависимости от того, насколько сложен DOM и, следовательно, сколько принудительных рефлоуингов.
В относительном смысле, анимация все еще меньше проблем на iPhone, чем S4. Это отражает наш более широкий опыт работы с iOS против Android — мы видели, что HTC One работает так же плохо, как S4. С другой стороны, Apple, похоже, намеревается сделать производительность браузера приоритетной, даже если это происходит за счет появляющихся стандартов (рассмотрите недавнее удаление поддержки теневого DOM из webkit, чтобы помочь достичь производительности 60fps ).
Вывод
Люди думают, что CSS3 решит все проблемы с производительностью анимации, но это не тот случай, когда макет пересчитывается. В то время как это может звучать как крайний случай, это не большая просьба о расширении аккордеона гладко.
Хотя в приведенных мною примерах рассматриваются самые основы, влияющие на производительность переходов на мобильных устройствах, существует множество облегченных библиотек, которые могут дополнительно оптимизировать переходы, чтобы они выглядели более плавными для конечного пользователя. Тем не менее, вы могли бы также утверждать, что гладкий, подобный нативу опыт принадлежит самим нативным приложениям, и что веб-приложения должны в первую очередь функционировать над формой.
Исходя из всего вышесказанного (кроме «не откусывайте больше, чем вы можете пережевывать»), можно сказать, что уменьшение влияния повторений на DOM играет большую роль в работе веб-страницы. Вы можете достичь этого, уменьшив глубину и сложность DOM, или очистив неиспользуемые или избыточные CSS-селекторы. Анимационные элементы, имеющие абсолютное положение или фиксированное положение, также не позволят им вызвать перекомпоновку своих родительских элементов.
В качестве альтернативы, мы можем надеяться, что обновление смартфонов в этом году (включая только что анонсированную Galaxy S5) принесет нам еще большую вычислительную мощность и, наконец, позволит плавно открывать аккордеоны. В противном случае всегда есть телефоны следующего года … или год спустя …