Вскрытие производительности веб-эффектов для изображений
Опубликовано: 2022-03-10По мере того, как браузеры постоянно улучшают свои возможности графического рендеринга, возможность по-настоящему проектировать в них становится все более реальной. Несколько строк кода теперь могут оказать быстрое и впечатляющее визуальное воздействие и обеспечить согласованность без особых усилий . И, как и в большинстве случаев в веб-разработке, часто существует множество способов добиться одного и того же эффекта.
В этом посте мы рассмотрим один из самых популярных графических эффектов, оттенки серого, и оценим как простоту реализации, так и влияние на производительность холста HTML, SVG, фильтров CSS и режимов наложения CSS. Какой из них победит?
Дальнейшее чтение на SmashingMag:
- Вскрытие производительности веб-эффектов для изображений
- HTML5: факты и мифы
- Эффективное изменение размера изображения с помощью ImageMagick
- Умные методы оптимизации JPEG
Фильтры в Интернете работают как линза, наложенная на изображение. Они применяются к изображению после того, как браузер отрисовывает макет и начальную отрисовку. В поддерживаемых браузерах фильтры могут применяться индивидуально или накладываться друг на друга. Поскольку они могут быть применены в качестве модификации изображения после первоначального рендеринга и, вероятно, являются улучшением, фильтры изящно деградируют, просто будучи невидимыми в браузерах, которые их не поддерживают.
CSS-фильтры
Давайте начнем с самого простого метода создания эффекта оттенков серого: скромного, но мощного фильтра CSS.

Чтобы добиться этого эффекта, мы добавляем одну строку CSS: filter: grayscale(1)
. Этот фильтр обесцвечивает изображение и может использоваться с любым числовым или процентным значением от 0 до 1 (или от 0% до 100%). Примечание. В настоящее время фильтры для браузеров на основе WebKit должны иметь префикс -webkit-
. Однако такое решение, как Autoprefixer, избавит от необходимости добавлять их вручную.
Живая демонстрация — фильтр CSS
.cssfilter-gray { -webkit-filter: grayscale(1); background: url('img/bird.jpg'); filter: grayscale(1); }
Режим наложения фона
Режимы наложения CSS предоставляют бесконечное разнообразие вариантов комбинаций эффектов изображения. Существует два способа использования режимов наложения: свойство mix-blend-mode
и свойство background-blend-mode
.
-
mix-blend-mode
— это свойство, которое описывает, как элемент будет смешиваться с содержимым позади него. -
background-blend-mode
используется для элементов с несколькими фонами и описывает взаимосвязь между этими фонами.
Мы будем использовать background-blend-mode: luminosity
для наложения каналов яркости на серый фон в нашем примере, в результате чего получится изображение в градациях серого. Следует отметить, что порядок фона является постоянным: фоновые изображения всегда должны располагаться перед сплошными цветами или градиентным фоном, чтобы эффекты отображались должным образом . Цвет должен быть последним фоновым слоем. Это также защита от старых браузеров, которые не поддерживают background-blend-mode
— изображение все равно будет отображаться без эффекта.
Единственная разница с режимами наложения и фильтром CSS заключается в том, что теперь у нас есть несколько фонов, и мы используем background-blend-mode: luminosity
, который берет значения яркости из верхнего изображения (тестер птиц) и накладывает эти значения яркости на серый второй фон.
Живая демонстрация — режим наложения фона
.cssfilter-gray { background: url('img/bird.jpg'), gray; background-blend-mode: luminosity; }
На данный момент это самый новый и, следовательно, наименее поддерживаемый вариант, хотя он по-прежнему хорошо работает в Chrome и Firefox и имеет частичную поддержку Safari. Примечание. Safari поддерживает все режимы наложения, кроме режимов наложения на основе HSL: оттенок, насыщенность, цвет и яркость.
Холст HTML5
HTML5 <canvas>
обеспечивает массу гибкости, когда дело доходит до манипулирования изображениями, потому что у нас есть доступ к данным каждого отдельного пикселя (в частности, через canvasContext.getImageData
) и мы можем манипулировать каждым из них через JavaScript. Однако этот метод является наиболее сложным и сопряжен с наибольшими накладными расходами. Он также имеет несколько нюансов в вопросах кросс-происхождения из соображений безопасности.
Чтобы исправить ошибку перекрестного происхождения в Chrome, ваше изображение должно быть размещено на дружественном для совместного использования ресурсов (CORS) сайте, таком как GitHub Pages или Dropbox, и указать crossOrigin="Anonymous"
. Смотрите живой пример для демонстрации.
Способ достижения эффекта оттенков серого с помощью <canvas>
состоит в том, чтобы удалить красный, зеленый и синий компоненты из любого выпадающего значения в значении пикселя, сохраняя при этом уровень его светимости (яркости). Один из способов сделать это — усреднить значения RGB следующим образом: grayscale = (red + green + blue) / 3;
.

В приведенном ниже примере мы используем значения RGBa в формате (R,G,B,a)
в данных изображения; красный канал — это data[0]
, зеленый канал — это data[1]
и так далее. Затем мы получаем уровень яркости каждого из этих каналов (яркость) и усредняем их, чтобы превратить изображение в оттенки серого.
Живая демонстрация — холст HTML5
SVG-фильтр
Фильтры SVG имеют самую широкую поддержку (даже в Internet Explorer и Edge!), а также (почти) так же просты в использовании, как и фильтры CSS напрямую. Вы можете использовать их с одним и тем же свойством filter
. Фактически фильтры CSS произошли от фильтров SVG. Как и в случае с холстом, фильтры SVG позволяют выйти за пределы плоской плоскости двумерных эффектов, поскольку вы можете использовать затенение WebGL для создания еще более сложных результатов.
Есть несколько способов применить SVG-фильтр, но в этом случае мы по-прежнему будем использовать свойство filter
для фонового изображения, как и в примере с фильтром CSS для согласованности. Самая большая разница с фильтрами SVG заключается в том, что мы должны быть осторожны, чтобы включить этот фильтр и связать его с правильным путем. Это означает, что нам нужно импортировать SVG на страницу над элементом, в котором мы его используем (что можно упростить, используя механизм шаблонов и операторы включения).
Живая демонстрация — фильтр SVG
<svg> <filter> <feColorMatrix type="saturate" values="0"/> </filter> </svg>
.svgfilter-gray { background: url('img/bird.jpg'); -webkit-filter: url(#grayscale-filter); filter: url(#grayscale-filter); }
Производительность фильтра
Итак, как они складываются, когда дело доходит до начальной производительности рендеринга? Я создал тестовую страницу для каждого из них и использовал функцию сравнения WebPagetest в Chrome 47. Учитывая, что каждый тест давал несколько разные результаты, общую тенденцию можно резюмировать следующим образом:
Фильтр CSS, фильтр SVG и методы режима наложения CSS загружаются в относительно одинаковые временные рамки. Иногда фильтр SVG работал быстрее, чем режим наложения CSS (но всегда чуть-чуть) и наоборот. Фильтр CSS, как правило, загружался одним из самых быстрых, а <canvas>
всегда был самым медленным. Это наиболее важное понимание, полученное. <canvas>
регулярно отставал от других методов рендеринга изображения.
Справедливости ради я хотел также сравнить время загрузки нескольких изображений. Я создал десять представлений каждого (вместо одного) и снова запустил тесты:
Результаты были схожими (имейте в виду, что в каждом тесте были небольшие различия). Фильтр CSS в этом случае был на 0,1 мс медленнее, показывая, что между фильтрами CSS, режимами наложения и фильтрами SVG результаты для самого быстрого метода неубедительны. Однако HTML5 <canvas>
заметно отставал в сравнении.
При более глубоком рассмотрении времени загрузки страницы с помощью рендеринга JavaScript и времени рендеринга рисования вы можете увидеть, что эта тенденция продолжается.

Тип фильтра | Время рендеринга | Время рисовать |
---|---|---|
CSS-фильтр | 12,94 мс | 4,28 мс |
Режим наложения CSS | 12,10 мс | 4,45 мс |
SVG-фильтр | 14,77 мс | 5,80 мс |
Фильтр холста | 15,23 мс | 10,73 мс |
Опять же, <canvas>
занял больше всего времени на рендеринг и больше всего времени на отрисовку, в то время как два варианта CSS были самыми быстрыми, а SVG оказался посередине.
Эти результаты имеют смысл, потому что <canvas>
берет каждый отдельный пиксель и выполняет над ним операцию, прежде чем мы вообще сможем увидеть какое-либо изображение. Это требует много вычислительной мощности во время рендеринга. Хотя обычно SVG используются для векторной графики, я все же настоятельно рекомендую использовать их вместо <canvas>
при работе с эффектами растрового изображения. Мало того, что SVG быстрее, с ним гораздо проще работать и он более гибкий в DOM. Как правило, фильтры CSS даже более оптимизированы, чем фильтры SVG, поскольку исторически они являются ярлыками, возникающими из фильтров SVG и, таким образом, оптимизированными в браузерах.
#нет фильтра
А если без фильтра? Я сравнил наш общий самый быстрый метод (добавление фильтра CSS) с редактированием вашего изображения в программном обеспечении для редактирования фотографий перед его загрузкой (я использовал предварительный просмотр в Mac OS X, чтобы удалить насыщенность). При предварительном редактировании изображения я обнаружил в своих тестах постоянное улучшение производительности на 0,1 мс:
Заключение
Фильтры изображений — это интересный и эффективный способ обеспечить визуальное единство и эстетическую привлекательность в Интернете. Имейте в виду, что они немного снижают производительность, но также имеют преимущества быстрого дизайна в браузере и возможности проектирования взаимодействия с.
Для простых эффектов изображения используйте фильтры CSS, так как они имеют самую широкую поддержку и самое простое использование. Для более сложных эффектов изображения воспользуйтесь фильтрами SVG или режимами наложения CSS. Эффекты фильтра SVG особенно хороши из-за их возможностей манипулирования каналами и feColorMatrix
. Режимы наложения CSS также предлагают несколько действительно приятных визуальных эффектов с перекрывающимися элементами на странице. Вы можете использовать аналогичные режимы наложения в SVG (например, feBlend
), хотя они похожи на CSS background-blend-mode
в том смысле, что взаимодействие относится к самому SVG, а не к окружающим элементам, как это позволяет mix-blend-mode
. Просто не используйте <canvas>
для фильтров.