Что мы имеем, и как мы используем это. Глобально есть три способа:
- Вставка исходного кода SVG иконки прямо в DOM страницы.
- С помощью HTML тега IMG
- С помощью CSS background-image
Мы не будем говорить о варианте вставки иконок в виде шрифтов, ибо у этого подхода есть масса недостатков (некоторые из них чисто субъективны), о которых можно узнать с помощью поиска в Гугл, и вариант с IFRAME и OBJECT тегами тоже опустим по той же причине.
У всех этих способов есть свои достоинства и недостатки. С появлением SVG у нас появились новые требования к иконкам. Например, во времена PNG нам и в голову бы не пришло использовать одну и ту же иконку в разных размерах в разных частях сайта и с разными цветными заливками. Для этого нам пришлось бы попросить у дизайнера несколько иконок с разными цветами и размерами. Но с появлением SVG мы озверели и начали одну и ту же иконку вставлять повсюду, так как появилась возможность в соответствии с желаниями изменять вид иконки с помощью CSS.
Приведу пример:
Есть у нас иконка — звездочка для рейтингов. Где-то она белая, где-то желтая, большая и маленькая. Плюс может быть обрезанная половинка звездочки, скажем, для обозначения рейтинга 2.5 или 4+.
Для реализации данного примера нам нужно как минимум четыре PNG иконок для каждого цвета и формы, но если у нас SVG, то вместо четырех мы спокойно можем обойтись и одной единственной, специально оформленной для данной задачи и не только.
Нашу звездочку можно прямо вставить в DOM и с помощью стилей оформить ее так, как нам нужно. Это первый вариант, знакомая нам практика.
В первом варианте из достоинств можно перечислить удобное управление элементами графики, анимацию отдельных частей иконки и т.п., полное управление SVG тегами. Из недостатков первое, что в этом случае мы получаем большой размер DOM, что по некоторым причинам является не совсем хорошим феноменом. Вторым недостатком, по сравнению с третьим вариантом, является то, что размер, позиционирования (центровка по вертикали и горизонтали) является в некоторых случаях не тривиальной задачей.
А что насчет второго варианта, то он самый избыточный, так как не имеет ни одного из достоинств двух других вариантов.
Что у нас получается? Мы имеем два варианта вставки иконок, у которых есть свои достоинства и между которыми иногда бывает сложно сделать выбор.
А теперь представьте, что вы можете использовать почти все достоинства (кроме анимации отдельных частей иконки) первого варианта наряду с третьим вариантом.
То есть вставлять иконки с помощью CSS background-image, или HTML тега IMG, и по вашему усмотрению изменить цвет каждого тега в SVG, будь то path, polygon или circle, не имеет значения.
Вот как это будет выглядеть:
background-image: url(star.svg?p=red,$00ff00,,green);
или
<img src=”star.svg?p=red,$00ff00,,green”>
Думаю, что идея ясна, синтаксис уже зависит от настроек сервера, а над реализацией еще надо поразмышлять.
Тут ссылка того, как я решил для себя эту проблему. Приветствуются любые решения, если они крутые.
Как это работает
- caches — папка для кэша
- colors — папка для хранения оригинальных цветов иконок
- icons — папка для отформатированных иконок
- originals — папка, куда скачиваются все иконки (ее можно задать и вручную)
Пример использования данной реализации.
icon/?p=parse /* запускает цикл работы */
icon/?p=empty /* удаляет все файлы, созданные вследствии работы команды parse */
background-image: url("icon/?p=leaderboard,red,blue,$000,green,orange,yellow,$0f0");
background-image: url("icon/?p=leaderboard,red,blue,$000");
background-image: url("icon/?p=leaderboard,,blue,$000,orange,red");
background-image: url("icon/?p=history");
background-image: url("icon/?p=history,$ff0000");
С точки зрения перформанса это не самая лучшая идея, даже если будет кэш, все равно это уже не будет выдача статика, там уже все равно будет работать скрипт, хотя можно использовать такую вставку только тогда, когда нужен другой цвет для иконки, но для больших проектов, где иконки становятся головной болью и в этом притоне не найдешь даже родного брата, то как по моим наблюдениям для таких проектов, пока что такой вариант может считаться — best practice.
P.S.: Пока что не успел на продакщене использовать, сижу гадаю, что можно еще подправить, или с какими проблемами можно столкнутся с этим, так что приветствуется любая критика, заранее спасибо.
P.S.S.: Дельный способ настройки сервера предлагает пользователь AlexLeonov habrahabr.ru/post/278825/#comment_8799315
Комментарии (20)
psrafo
09.03.2016 12:30-1Не для каждой иконки, а только тогда, когда нужно изменить цвет, хотя может быть так, что половина иконок именно будет работать через это. И да, это не очень круто, но если включить в дело Varnish + кеш браузера, то потери думаю, будут минимальными.
xtech
09.03.2016 13:26+1Понятное дело, что если все закэшировать, то и за производительностью можно не следить, но это же не совсем верный подход?
psrafo
09.03.2016 13:32Почему же не верный ?
xtech
09.03.2016 13:42Не буду утверждать, абсолютную верность утверждения, но:
Кэширование — это самый последний механизм, который стоит применять, когда все другое уже перепробовано и дальше оптимизировать либо нечего, либо невозможно.psrafo
09.03.2016 13:57Как я думаю, она верно для большинства, но не для всех случаях. А верно она в данном случае, думаю это уже на любителя.
Я лично кэшов не стесняюсь, если они разумны.
artemmalko
09.03.2016 12:48А как же спрайт символов? А как же стек?
При этом обоих этих подходах можно модифицировать цвета. + есть плагины для работы с этим через CLI или Gulp/Grunt/что-то еще.psrafo
09.03.2016 13:01Про спрайт символов могу сказать, а как же старые версии платформ, которые его не поддерживают? А про стек впервые слышу, спасибо.
artemmalko
09.03.2016 13:15По умолчанию не все поддерживают спрайт символов из внешнего файла (легко полифилится, svg4everybody), а в остальном нет проблем. Вот стек да, не везде поддерживается без полифилов, но я его добавил для примера, так как это будущее SVG.
psrafo
09.03.2016 13:27В будущем да, наверное все будет через спрайн, но пока, есть люди, которые полифилов не используют, и на то есть свои причины, там нативность, простота, прозрачность и т.п.
Да и будущее это не ясно, когда придет.artemmalko
09.03.2016 13:56В будущем будет стек, как раз. А настоящее — это symbols.
extempl
09.03.2016 15:51Всё-таки symbols не дают свободу настройки изображений с несколькими цветами.
xtech
09.03.2016 13:45Да вот еще добавлю, при сложных svg можно запутаться с назначением цветов, Как мне узнать в каком порядке цвета, если иконку делал не я?
psrafo
09.03.2016 13:52Это проблема, да, но лично для меня и моей команды она не является таковым, ибо даже если мы скачаем какую-то иконку, дизайнер все равно что-то с ним делает, прежде чем она доберется до разработчика.
Nadoedalo
09.03.2016 16:57-1эм, а смысл если можно:
1) Рано или поздно вставлять картинки-svg в shadow dom(в таком случае это будет ~аналогично 1 методу без недостатка "раздутие оригинального DOM"). Там, вообщем-то, даже аргументы будут
2) Взять ровно тот-же скрипт который будет искать определённые html-теги и напрямую их вставлять в нужные места, а всё остальное — с помощью CSS?
вообщем преимущества спорны. Очередной костыль в котором никто кроме автора не разберётся + среда разработки будет ругаться и выдавать, как минимум — варнинги.
+ автор, ты представляешь сколько из-за смены цвета картинки будет перерисована вся страница? Любое изменение css заставляет страницу отрендерится заново всю, потому что неизвестно какие элементы могли быть задеты.psrafo
09.03.2016 18:25Если вы в этом не видите смысла, наверное, оно не для вас.
Очередной костыль в котором никто кроме автора не разберётся
Я не настаиваю, возможно моя реализация отстойна, она просто идет в бонус. Я просто предлагаю способ/метод/подход к решению проблемы.
сколько из-за смены цвета картинки будет перерисована вся страница?
Нет, я не представляю, сколько раз вся страница будет перерисована, потому что она этого делать не будет. Данный метод для браузера ничем не отличается от тех, что мы используем сейчас.
Да и вообще, вы вцепились в мою реализацию, но ведь статья не про него — главное метод.
1) Рано или поздно вставлять картинки-svg в shadow dom(в таком случае это будет ~аналогично 1 методу без недостатка "раздутие оригинального DOM"). Там, вообщем-то, даже аргументы будут
2) Взять ровно тот-же скрипт который будет искать определённые html-теги и напрямую их вставлять в нужные места, а всё остальное — с помощью CSS?
Не могу найти связь с нашей темой, извините.
AlexLeonov
09.03.2016 17:46+1Гм.
Шаг первый. Настраиваем сервер так, чтобы он существующие файлы отдавал напрямик, а при запросе несуществующих — отправлял запрос на нечто вроде image.php
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.*)$ image.php [QSA]
или
location / { try_files $uri $uri/ /image.php?$args; }
Шаг 2.
В image.php понимаем, что нам надо, используем всю мощь разбора URL, формируем из шаблона SVG готовый SVG подстановкой параметров, кладем его в заранее определенную папочку на сервере и отдаем клиенту.
Шаг 3.
Кто-то приходит за картинкой второй раз. См. шаг 1.psrafo
09.03.2016 18:29Ага, добавлю ссылку в конце статьи, спасибо.
AlexLeonov
09.03.2016 21:52Да не за что. Это совершенно стандартный и избитый способ формирования, например, миниатюр
src="bigpicture.w200.jpg"
=>
image.php?request=bigpicture.w200.jpg
ну а дальше уже любой PHP-шник вам накидает более-менее нормальный скриптик за 15 минут, если дадите ему четкие инструкции, что и куда нужно подставлять
xtech
Мне кажется, что как раз производительность в данном случае будет играть большую роль, нежели какое-то удобство настройки иконок в проекте. Как никак +1 скрипт, который будет выполняться для каждой иконки против обычной отдачи статики nginx'ом и кэшированием самим браузером.
Ваш подход конечно интересный, но как мне кажется не очень жизнеспособный.
ckr
Вы правы. На php в таком виде решение выглядит нелепо.
Можно переконфигурировать так, чтобы nginx смотрел сначала есть ли файл в кэше, а уж потом при отсутствии оного вызывал какой-нибудь icon.php, который бы в свою очередь сгенерировал иконку и сохранил результат в кэш:
Как по мне, для маленькой проблемы довольно сложный процесс развертки. Стоит учесть, что фронтендом иногда занимаются специалисты, не соображающие в php или настройку nginx. Или, даже соображающие, но просто не хотящие разворачивать этот ад в каждом проекте.
На node.js решение выглядело бы интереснее. Держа шаблон svg-икноки в оперативной памяти, node выстреливала бы готовые файлы быстрее nginx, который каждый раз читает статику с диска; и плюс не нужно сохранять кэш, а в процессе разработки шаблона сайта (например, подборе цветов иконок, их толщин линий) кэш вообще не нужен. Оформить это как подключаемый middleware. Было бы интересно!