Pull to refresh

Как проектировался новый Photo Viewer в Facebook

Reading time 6 min
Views 868
Original author: Stefan Parker
Это перевод поста из Facebook Engineering Blog, который интересен, наверное, даже не столько сутью решения, которое в нем описано, сколько рассказом о «кухне» разработки в Facebook. Речь идет об обновленном функционале просмотра фотографий, который появился в конце сентября 2010 г. и был немного еще улучшен на днях.

imageЗадумавшись об обновлении Photo Viewer, мы столкнулись с множеством трудностей. Очевидно, что фотографии это наиболее востребованная функция Facebook. Ежедневно наши пользователи загружают более 100 миллионов фотографий, а предназначенный для этого функционал был создан довольно давно и явно нуждался в доработке.

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

Как нам это удалось
Мы начали с составления списка текущих проблем:
  • Наибольшие проблемы возникали с надежностью. Изображения загружались медленно, и иногда процесс зависал на неопределенное время. Пользователям приходилось обновлять страницу в браузере, чтобы увидеть фотографии и комментарии к ним.
  • При просмотре фотографий из Ленты новостей приходилось либо открывать их в новой вкладке, либо мириться с тем, что после просмотра нужно было заново прокручивать ленту вниз, чтобы вернуться к предыдущей позиции. Для разбирающихся в компьютере людей это не составляло особых проблем, но многие из наших пользователей испытывали связанные с этим неудобства.
  • Функционал просмотра комментариев к фотографиям был также реализован не самым удобным образом. Процесс выглядел так – нужно было посмотреть фотографию, промотать страницу вниз, чтобы увидеть подпись и комментарии к ней, а потом вернуться обратно наверх, и так каждый раз.
  • JavaScript, предназначенный для загрузки и кэширования фотографий, а также для публикации комментариев, был также реализован не самым лучшим образом. Он оставался неизменным на протяжении многих лет, на фоне того, что технологии работы браузеров и требования к ним значительно ушли вперед.

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

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

image
Первоначальная концепция Photo Viewer

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

image
Первоначальный прототип Photo Viewer

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

image
Полноэкранная версия окна Photo Viewer

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

В итоге мы определили следующие критерии для разработки дизайна:
• В нижней части фотографии должно оставаться минимум 100 пикселей для подписи и комментариев, которые должны быть всегда видны на экране. Это означало необходимость сжатия фотографий в тех случаях, когда экран пользователя обладает слишком низким разрешением.
• Всплывающее окно должно находиться поверх основной страницы и обеспечивать прокрутку при необходимости, однако сама страница на фоне должна оставаться неподвижной.
• Мы должны были обеспечить возможность легко добавлять новые функции без необходимости переработки API.
• Мы решили отказаться о поддержки новым функционалом браузера IE6, если объем работ и потери в производительности окажутся слишком велики по сравнению с выгодой от работы с этой версией.
• Мы должны были минимизировать использование JavaScript.

Итоговое решение: Больше CSS, намного меньше JavaScript
Итоговое решение было основано на использовании возможностей CSS для работы с всплывающим окном без необходимости применения JavaScript. Давайте взглянем на HTML и рассмотрим построчно использованный код.

image
  1. Сначала нам нужно создать лайтбокс. За счет использования корневого тега с фиксированной позицией, fbPhotoTheater, нам удалось отделить контент от body. Задав корневому тегу width и height 100% и установив для body параметр overflow в значение hidden, мы можем прокручивать содержимое без изменения самой страницы в фоне.
  2. Элемент container задает границы содержимого лайтбокса по горизонтали в размере 960px и положение лайтбокса в центре экрана. После настройки структуры лайтбокса, остальные элементы используются для корректного позиционирования его содержимого.
  3. Элемент positioner имеет height 100% и max-height 820px. Из них 720 пикселей отводится под саму фотографию, а оставшиеся 100 пикселей используются для подписей и комментариев в нижней части лайтбокса. Это достигается за счет позиционирования photoInfoWrapper на высоте 100 пикселей от нижней границы positioner. Таким образом, он всегда будет примыкать снизу к stageWrapper.
  4. Элементы stageBackdrop, stageWrapper и stageActions должны иметь одинаковое позиционирование в рамках CSS. Так обеспечивается их взаимное перекрытие. Мы задаем им max-height 720 px, top 0 и bottom 100px. Благодаря такой величине bottom у нас гарантированно остается 100 пикселей внизу экрана для подписей, а max-height сохраняет содержимое лайтбокса в допустимых пределах даже для слишком вытянутых по высоте фотографий. Также для stageWrapper мы задаем значение text-align:center, чтобы фотография занимала центральную позицию по горизонтали.
  5. Элемент stage используется для центрального позиционирования фотографии по вертикали. Это единственный случай использования JavaScript при позиционировании. Для stage нам нужно задать значение line-height, равное его height, за счет этого дочерний элемент img получает позиционирование vertical-align: middle. Стоит отметить достоинство данного решения, которое заключается в том, что расчет нужно сделать только однажды, а не каждый раз, когда пользователь пролистывает несколько фотографий.
  6. Для самого изображения задается max-height 100%, чтобы оно всегда помещалось в границы панели.
  7. Наконец, для элемента photoInfoWrapper, который должен находиться под элементом positioner, задается относительное позиционирование top: – 100px. За счет этого происходит заполнение пустого интервала.


Закончив с разметкой, мы приступили к пересмотру содержимого JavaScript. Старая версия функционала загружала фотографии пачками по 20 штук вместе с подписями, комментариями и т.д. при помощи AJAX. В результате чего, запросы занимали в три раза больше времени, чем если бы мы грузили только фотографии. Отделив изображения от сопутствующей информации, мы получили дополнительный выигрыш в производительности. Теперь с каждым запросом AJAX мы можем грузить больше фотографий и меньше сопутствующих данных, оптимизируя время отклика на запрос. Чтобы обеспечить максимальную скорость загрузки фотографий, мы отслеживаем, в какую сторону их листает пользователь, и подгружаем следующие 5 фотографий. Благодаря этому фотографии заблаговременно попадают в кэш браузера, и их отображение происходит незамедлительно.

При загрузке данных мы отделили информацию о них от JavaScript-класса PhotoTheater. В ответ на каждый запрос на получение данных приходит объект с ключами, содержащими идентификаторы элементов Photo Viewer, и HTML код, которые нужно вставить в эти элементы. Мы реализовали цикл, в рамках которого мы задаем содержание каждого элемента. Благодаря такому решению мы можем менять дизайн и разметку HTML, не внося изменения в JavaScript. Наконец, чтобы максимально повысить скорость загрузки, к каждой пиктограмме фотографий мы привязали атрибут HTML5, содержащий URL полной версии. Таким образом, когда пользователь кликает пиктограмму мы можем получить URL из ее атрибутов и показать первую фотографию без использования запроса AJAX. Таким образом, среднее время загрузки функционала для просмотра фотографий теперь составляет менее половины секунды.

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

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

image
Итоговая версия функционала для просмотра фотографий.
Tags:
Hubs:
+54
Comments 37
Comments Comments 37

Articles