[Из песочницы] SVG, Iconfonts vs PNG

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

Признаться, я был немного удивлен реакцией на такие мысли в 2014-м то году. По этому случаю рассмотрим более детально существующие техники работы с иконками.

На текущий момент все более-менее просто. Мы можем верстать иконки с помощью SVG, создавать иконочные шрифты, ну и никуда не делась старая добрая техника с применением растра, в частности PNG. Правда добавились некоторые нюансы с появлением кучи HDPI устройств с совершенно разной плотностью пикселей.

SVGСамую бурную реакцию вызвало именно применение SVG. Сначала юзер franzose заметил что: Только вот вес у сложного вектора гораздо больше. И шансов подвесить браузер тоже

Так как в статье речь шла преимущественно о иконках — такой коммент для меня совершенно непонятен. Да, я сам несколько раз получал от дизайнера ужасные иконки, которые представляли собой нагромождение примитивов, налепленных друг на друга. Но ничего не мешает подойти к дизайнеру и сказать, — «что за херня, мужик?!», ну или самому зафиксить это дело в том же иллюстраторе, объединив в какой-нибудь общий shape (ну это конкретно мой случай, других «сложных векторов» я не видел пока). Еще для этих целей можно использовать SVGO. Кажется объединение в общий shape — это единственная его часть, которая действительно драматически влияет на производительность.На самом деле даже если забыть про все эти вещи с иконками — я не могу представить какого-нибудь хоть минимально часто встречающегося кейса про «сложный вектор». Да все равно вектор, применительно к задачам сегодняшнего веба будет меньше растра (это про вес).

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

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

На самом деле я считал что абсолютно во всех браузерах SVG, прилепленный через background-image кэшируется по самое нехочу. Мы ведь именно об этом случае говорим? На практике все оказалось немного сложнее.

Я пообщался с парой людей, которые занимаются SVG частью в Chrome и Firefox и показал им вот это демо, которое Adrian Osmond делал еще год назад для, в принципе, таких же целей. Но тогда все было на порядки хуже. Почему, можно почитать в его статье и багтрекере вебкита.

Итак:

Chrome 761313cae1724aebbb4c51e860c6f570.pngFPS проседает примерно раза в полтора, два. Печально конечно, но не 10x все же. Так что же происходит под капотом Хрома в этот момент? Я немного почитал исходники на chromium.org, нашел кое-какой кэширующий код для SVG, и это меня запутало еще сильнее. Тут я решил спросить у знающих людей.

Philip Rogers из Google, который в общем то и пишет большую часть всяких дел с SVG в хромиуме, сказал что различия отрисовки SVG и PNG несколько сложнее. Во-первых PNG декодируется в отдельном потоке, а SVG в главном, а во-вторых помимо производительности есть еще такие вещи, как например, память. В общем они решили отказаться от хранения кэша для svg чтобы сэкономить памяти. Как по мне — так это какой-то сомнительный план. Не совсем понимаю почему бы не кэшировать все это дело. Bitmap, которым заканчивается рендер не будет каких-то неприличных размеров, с сегодняшними то объемами памяти, даже на мобильных устройствах. Ну и грядет же вектор, тема перспективная. Но видимо поэтому в Google работают они, а не я.

Так что да, в хроме SVG отсчитывается заново каждый фрейм. Правда Philip сказал что они там что-то придумали, что «should bring it much closer to png performance». Будет в следующей Canary. Посмотрим. Тем не менее производительность на уровне чуть меньшем чем 60 FPS (а у меня в общем средний такой конфиг) на огромной куче иконок одновременно находящихся на экране — это вполне себе адекватная производительность.

Firefox Я не знаю чем померить FPS в FF (видел какую-то софтину, но процесс инсталляции был не совсем тривиален и я не стал возиться), но на глаз производительность PNG и SVG одинаковая. Так же думает и Robert Longson, контрибьютор SVG в Firefox. По словам Роберта, в Firefox есть кэш для всех изображений и разница между SVG и PNG может заключаться разве что в том, что SVG немного дольше «декодируется» при первой отрисовке, что вполне закономерно.Таким образом в FF мы вообще имеем идентичную производительность, если не производим каких-либо манипуляций инвалидирующих SVG кэш. Естественно, скролл ничего не инвалидирует. Возможно есть еще какие-то моменты, но драматически производительность они ухудшить не могут.

IE d48fa2bfa742492d95298eab26af2a31.pngНовые IE часто бывают очень хороши во всяких неочевидных местах, например WebGL. Тут такая же ситуация. В IE демо работает намного лучше чем в 2-х предыдущих браузерах, показывает одинаковый framerate для SVG и PNG. Но делает это по каким-то магическим причинам не сразу.

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

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

С практиками верстки SVG все более-менее понятно. Я предпочитаю рисовать SVG спрайты. Техника такая же как и для растровых спрайтов. Проблемы решаемые ими в принципе такие же. Естественно есть куча разных плагинов для этих целей, например вот.Еще можно делать это с помощью data url. Тут я рекомендую вот такую штуку и их же софтину вот тут, для тех, в чей процесс Grunt по каким-то причинам не входит. Ну еще можно прям файлами на background-image, но не нужно.

Единственный современный браузер где я видел проблемы с рендерингом SVG — это IE на Windows Phone. Но там эта проблема решаема.

Iconfonts Если в SVG мы в принципе можем нарисовать все что душе угодно, то с помощью шрифтов ограничены монохромными иконками (если не брать во внимание извращения вроде stackicons), что в рамках текущих веяний в дизайне не представляется таким уж недостатком. Зато перед нами открывается куча возможностей начиная от банальной смены цвета и размера, заканчивая пачкой CSS манипуляций с шрифтами, вроде тенюшек и т.д. Техника с иконочными шрифтами сложнее чем те же SVG. Тут нужно обладать некоторым объемом знаний в областях, где не каждый дизайнер ориентируется. Казалось бы, делов то, запихай свои SVG-хи в один из кучи онлайн-упакавщиков типа того же Icomoon-а или настрой какой-нибудь Grunt\Gulp плагин, и будет тебе счастье.

В комментариях к статье главным обвинением относительно шрифтов было что-то вроде

рендеринг ужасный в мелких размерах (явные лесенки) © designiac

А что вы хотели, ребят? Нарисовать огромную иконку приблизительно кегля так 48-го, проработать мелкие детали, потом воткнуть ее кеглем так 12-м и вместо удивления о каком-то плохом рендере этих ужасных вебшрифтов, наслаждаться идеальными чистыми иконками? Хинтинг! Вот основная вещь, которую нужно знать про iconfonts. Вот он, святой грааль иконок в вебе! Я считаю что если вы точно знаете что скажем, цвет иконок или их размер не изменятся (вероятно бывает и такое), нужно брать SVG и не морочить голову. Использовать шрифты без необходимости — какой-то не очень критичный конечно, но все равно overhead.Чтобы собрать годный шрифт нам понадобятся:

иконки в векторе аналог icomoon-а профессиональная штуковина для работы со шрифтами. Я использую FontLab Studio Чтобы было понятно зачем нам это вообще нужно — вот такой пример: берем модный Font Awesome и одним хинтом делаем из вот такой иконки pinterest:

e4a66035d0734e2c81304d6bc39b53c9.png

вот такую:

3176175ce6fc42e397efa2c664555540.png

Лучше всего видно на мелком кегле, естественно.

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

b8341c9248ff4065bf6680bf7c46dd71.png

немного сложнее чем в такой:

d89e456ea79d4a148025cdec92efac00.png

Я не тот человек, который может авторитетно написать о хинтинге, поэтому делать этого не буду. Буду рад если придет серьезный шрифтовик и напишет детальную статью. Нужно просто брать во внимание то, что он (хинтинг) существует. И это не шрифты криво рендерятся, это некоторые разработчики не хинтируют их совсем, или лепят автохинты (которые, надо сказать, неплохо спасают временами).

Субпиксельное сглаживание Ну, все что нужно знать о субпиксельном сглаживании — это то, что оно есть. Версию назад с этим были проблемы в хроме, но сейчас все работает так, как должно.PNG Недостатки растровой графики с такой необходимостью учитывать HDPI устройства, какая есть сейчас — очевидны. Возможно, если бы плотность ограничивалась 2 вариантами ретина\не ретина — это было бы достойным вариантом, и мало кому в голову пришло бы заморачиваться со всеми неоднозначностями вектора, существующими сейчас в вебе. Но у нас есть 1.5x, 2x, 3x устройства. И собирать спрайты под каждое из них уже не кажется достаточно изящным вариантом.С другой стороны у растра без потерь есть достоинство, которое, лично для меня, перекрывает все недостатки в обслуживании — он стабилен. Можно быть точно уверенным в том, что как ты иконку нарисуешь — так она и будет выглядеть в итоге. Пиксель в пиксель. Вопрос лишь в том, нужна ли такая точность в каждом конкретном случае.

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

Пари Так вот, зачем я все это написал? Я предлагаю юзерам, негативно отозвавшимся о производительности и рендере векторных иконок, в том посте, с которого все началось, или сочувствующих им и их точке зрения, пари.Вы предоставляете мне верстку или какой-то конкретный сайт (что лучше), иконки на котором сейчас заверстаны в PNG и под ретину и под простые дисплеи, исходники иконок которого у вас есть в векторе, который при любых эффектах выдает 60FPS на средней машине. Сразу оговоримся что объективно это должен быть обычный сайт. Не онлайн софтина по работе с иконками и не пример из этой статьи.Я заменяю растр на вектор и оптимизирую какими хочу способами.

В итоге должна получиться страница, на которой FPS проседает не больше, скажем, 30%. О дальнейших условиях договоримся в процессе. Как вам? Докажем ущербность SVG?

© Habrahabr.ru