- PVSM.RU - https://www.pvsm.ru -

SVG, Iconfonts vs PNG

image

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

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

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

SVG

Самую бурную реакцию вызвало именно применение SVG. Сначала юзер franzose [2] заметил что:

Только вот вес у сложного вектора гораздо больше. И шансов подвесить браузер тоже

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

На самом деле даже если забыть про все эти вещи с иконками — я не могу представить какого-нибудь хоть минимально часто встречающегося кейса про “сложный вектор”. Да все равно вектор, применительно к задачам сегодняшнего веба будет меньше растра (это про вес).

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

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

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

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

Итак:

Chrome

SVG, Iconfonts vs PNG

FPS проседает примерно раза в полтора, два. Печально конечно, но не 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

SVG, Iconfonts vs PNG

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

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

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

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

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

Iconfonts

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

Техника с иконочными шрифтами сложнее чем те же SVG. Тут нужно обладать некоторым объемом знаний в областях, где не каждый дизайнер ориентируется. Казалось бы, делов то, запихай свои SVG-хи в один из кучи онлайн-упакавщиков типа того же Icomoon-а или настрой какой-нибудь GruntGulp плагин, и будет тебе счастье.

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

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

А что вы хотели, ребят? Нарисовать огромную иконку приблизительно кегля так 48-го, проработать мелкие детали, потом воткнуть ее кеглем так 12-м и вместо удивления о каком-то плохом рендере этих ужасных вебшрифтов, наслаждаться идеальными чистыми иконками?

Хинтинг!


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

Чтобы собрать годный шрифт нам понадобятся:

  1. иконки в векторе
  2. аналог icomoon-а
  3. профессиональная штуковина для работы со шрифтами. Я использую FontLab Studio [9]

Чтобы было понятно зачем нам это вообще нужно — вот такой пример: берем модный Font Awesome [10] и одним хинтом делаем из вот такой иконки pinterest:

SVG, Iconfonts vs PNG

вот такую:

SVG, Iconfonts vs PNG

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

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

SVG, Iconfonts vs PNG

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

SVG, Iconfonts vs PNG

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

Субпиксельное сглаживание


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

PNG

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

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

Итог

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

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

Пари

Так вот, зачем я все это написал? Я предлагаю юзерам, негативно отозвавшимся о производительности и рендере векторных иконок, в том посте, с которого все началось, или сочувствующих им и их точке зрения, пари.

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

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

Автор: k3nny

Источник [11]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/svg/67602

Ссылки в тексте:

[1] Изображения в верстке. Хватит это терпеть: http://habrahabr.ru/post/231295/

[2] franzose: http://habrahabr.ru/users/franzose/

[3] вот это: http://codepen.io/adrianosmond/pen/LCogn

[4] статье: http://adrianosmond.com/using-svg-for-sprites-a-cautionary-tale/

[5] вот: https://www.npmjs.org/package/grunt-svg-sprite

[6] вот такую: https://github.com/filamentgroup/grunticon

[7] вот тут: http://www.grumpicon.com/

[8] designiac: http://habrahabr.ru/users/designiac/

[9] FontLab Studio: http://www.fontlab.com/font-editor/fontlab-studio/

[10] Font Awesome: http://fontawesome.io/

[11] Источник: http://habrahabr.ru/post/233443/