svg
AVIF в «Эгее»!
Как говорится, если нельзя, но очень хочется, то можно. «Эгея», как я писал не понимает формат AVIF, но мне его удалось
Изображение ниже я взял из своей заметки про Красную площадь в коронавирусный период. В оригинале оно весит 1,1 мегабайт в формате JPEG, в этой заметке используется сконвертированное изображение размером в 179 килобайт. Почувствуйте разницу.
Добавлено позднее: в небе, кстати, я отчётливо вижу артефакты сжатия, надо играть с параметром качества, прежде чем использовать. Но в остальном картинка как будто бы не попортилась.
Конечно, если ваш браузер не поддерживает AVIF, это будет не та разница, на которую я надеялся. Напишите мне, кстати, если картинка у вас не отображается — я хотел бы узнать что у вас за браузер и насколько он современный.
Итак, «Эгея» не поддерживает AVIF, но я её в «Эгею» вставил. Как же мне это удалось?
Дело в том, что «Эгея» поддерживает формат SVG, а SVG поддерживает внутри себя растровую графику, в том числе вставленную через протокол «data». Протокол «data» — это картинка, закодированная в текстовую строку, вида data:mime/type;encoding,encoded_data.
Вообще, SVG поддерживает и внешние ресурсы (то есть в теории способен подгрузить картинку снаружи), но при вставке через тег img (как в «Эгее») в нём это запрещено по соображениям безопасности.
Поэтому мысль такая — переводим графику в AVIF, кодируем в base64 («data» так умеет, а иначе бинарные данные не вставить),
Для конвертации я написал вот такой небольшой bash-скрипт (для работы требуется пакет ImageMagick):
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: $0 <picturename>"
exit 1
fi
NAME="$1"
NEWNAME="${NAME%.*}.svg"
WH=( $(identify -ping -format '%w %h' "$NAME") )
if [[ "$NAME" == *@2x* ]]; then
WH=( $(( ${WH[0]} / 2 )) $(( ${WH[1]} / 2 )) )
fi
cat<<XML > "$NEWNAME"
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 ${WH[*]}" width="${WH[0]}" height="${WH[1]}">
<image width="${WH[0]}" height="${WH[1]}"
href="data:image/avif;base64,$(convert "$NAME" "avif:-" | base64)"/>
</svg>
XML
echo "$NAME" to "$NEWNAME" was converted.Последовательность теперь у меня такая — готовлю графику в более привычном формате, запускаю скрипт, получаю файл SVG, вставляю его
Дополнение: уже сообщают, что
Use SVG
Поскольку «Макбук» у меня с «ретиной», я давно озаботился тем, чтобы продукт, разработкой которого я управляю, хорошо смотрелся и на «ретине» тоже. Я считаю за такими экранами будущее и не грех позаботиться об этом будущем уже в настоящем. Если уж и не внедрить везде, так хоть научиться верстать.
Одним из главных помощников в такой вёрстке является, без сомнения, формаг СВГ — формат векторной графики, который на данный момент поддерживают все распространённые браузеры (включая ИЕ, с девятой версии). Особенно приятно, что его можно включать прямо внутрь ХТМЛя, это очень удобно — если СВГ используется для кучи мелких значков на странице, то не будет лишних соединений с сервером — ведь всё грузится вместе с основным кодом.
Но встаёт другая проблема — проблема повторного использования. Если одни и те же значки присутствуют на странице в изобилии, страница будет распухать, что печально.
К счастью, есть выход. СВГ — гибкая штука, в этом формате есть возможность использования частей изображения повторно. Первым шагом нужно определить
<svg style="display:none">
<symbol id="folder" viewBox="0 0 49.833 67.167">
<!-- код не рабочий, только для примера -->
<path d="M15.938,67.…"/>
<path d="M3.59,30.531c…"/>
</symbol>
<symbol id="file" viewBox="0 0 49.833 67.167">
<path d="M12.233c0.…"/>
<path d="M3.28C2.76…"/>
</symbol>
</svg>Тут у нас два изображения — folder и file, на которые мы можем сослаться следующим образом:
<svg width="28" height="37">
<use xlink:href="#folder"/>
</svg>
<svg width="28" height="37">
<use xlink:href="#file"/>
</svg>Таких вставок может быть сколько угодно и все они будут использовать одни и те же изображения, описанные
svg.green {
fill: green;
}
svg.red {
fill: red;
}Классы можно повесить на ссылающиеся теги СВГ, жаль только этот способ полон ограничений. Кроме как в ФФ более избирательные селекторы использовать не удаётся — всё, что ниже тега use для таблицы стилей как будто не существует. Если и есть
Свёртка в вебе
Я
<style>
.edge {
-webkit-filter: url(#edge);
filter: url(#edge);
}
</style>
<svg style="width: 0; height: 0">
<filter id="edge">
<feConvolveMatrix kernelMatrix="-1 -1 -1 -1 9 -1 -1 -1 -1" />
</filter>
</svg>
<image src="sample.jpg" class="edge">Магические числа в матрице — специальное ядро.
Впрочем, и раньше можно было внедрить в ХТМЛ
С таким возможностями, немудрено, что онлайновых «фотошопов» развелось, как грязи. Немного помучавшись с консолью, можно найти способ как поменять матрицу и это тоже будет работать! Например, вот так меняется число по центру (где у меня в примере девятка записана):
var arr = document.getElementById('edge').childNodes;
for (var i = 0; i < arr.length; i++) {
if (arr[i].kernelMatrix) {
arr[i].kernelMatrix.baseVal.getItem(4).value = newvalue;
break;
}
}Осталось только соединить этот код с «крутилкой» и готов
SVG с fallback на не векторные форматы
Нравятся мне такие вещи. Алексей Тен из Яндекса придумал очень изящный способ внедрения СВГ в код с возвратом к растровому формату, если браузер не поддерживает СВГ:
<svg width="96" height="96">
<image xlink:href="svg.svg" src="svg.png" width="96" height="96"/>
</svg>Принцип виден из кода, я думаю, но я всё же расшифрую. Если браузеры поддерживают внедрение СВГ в ХТМЛ, то почти весь выше приведённый код будет для них значимым: кроме атрибута «src», его у тега СВГешного image не бывает и он будет отброшен. Соответственно, картинка загрузится из файла svg.svg.
Если же браузер СВГ в таком виде не понимает, то будет отброшен тег svg и атрибут «xlink:href», а тег image будет преобразован в img — это старая особенность браузеров, которой я тщетно пытался придумать применение. В этом случае будет загружен svg.png.
Я уже на сайте в одном месте использую этот трюк.
SVG-спрайты
Вчера ночью, эксперементируя с различными способами внедрения картинок в ХТМЛ, я понял, что уже все браузеры (кроме «Оперы Мини»), понимают СВГ прямо в коде страницы. А это значит, можно отказаться от CSS-спрайтов в пользу того, что можно назвать «SVG-спрайтами»:

Принцип,
Думаю, всем понятен код: в теге svg задаются размеры кусочка спрайта, в image обязательно нужно указать полные размеры картинки (для Ретины можно указать их в два раза меньше, если спрайт подготовлен к этому типу экранов), при помощи параметров x и y позиционируем в каком именно месте спрайта расположена наша картинка.
В комментариях спрашивают зачём это всё надо, чем это лучшее спрайтов в ЦСС.
Ну,
Прозрачный фон SVG в Хроме и Сафари
Владислав Шкодин написал статью на «Хабре», где рассказал как ему удалось победить старый баг в движке WebKit — если вставить SVG с прозрачным фоном в тег OBJECT, что «Сафари» и «Хром»
Решение очень простое. Прямо внутри файла SVG, после тега svg нужно написать следующее:
<style>
svg { -webkit-background-clip: text; }
</style>Мощь SVG и media queries
Вадим Макеев демонстрирует сейчас на фестивале «404» мощь SVG — картинка сама (через CSS media queries) изменяется для разных разрешений экрана, при масштабировании полноценное лого с текстом ужимается, текст сначала переносится, потом исчезает и остаётся один логотип.
Ребята, о таком применении SVG я даже и не думал, это очень круто.
Другой пример — внутри SVG выбирает один из внедрённых растров, опять же в зависимости от разрешения экрана (а можно, кстати, показывать специальную
Дополнено позднее: Вадим выложил слайды своего доклада (смотреть надо в «Опере»).
SVG и браузеры

Это таблица показывает насколько успешно проходят разные браузеры тесты SVG с сайта W3C (таблица с сайта CodedRead). В таблице, на мой взгляд, примечателен уровень поддержки SVG браузером IE 9 preview. Несмотря на уверения Microsoft о 100% уровне поддержки SVG, видно, что до идеала ещё делековато.
Я, правда, не понимаю что происходит и где правда. С одной стороны, таблица как бы говорит нам, с другой, на сайте IE9 написано следующее:
I want to thank the members in the W3C working groups that helped us develop these tests, the community members for providing valuable feedback on the tests, as well as the engineers on the IE team that made these possible
То есть тесты придуманы не самим Майкрософтом и наверняка в W3C их видели и одобрили. Где правда?
Raphaël — графические эффекты на JS
«Raphaël» — небольшая (18 килобайт) библиотечка для быстрого применения графических эффектов (на сайте есть примеры отражения, вращения картинки и текста) и работы с графическими примитивами.
Работает под Safari 3.0+, FireFox 3.0+, Opera 9.50+, IE 6.0+. Используются SVG и VML. Как видно, большинство браузеров самых последних версий, именно
Вертикальный текст: как?
Недавно возникла задача написания вертикального текста. Причём, именно текстом. В CSS3 есть свойство «
<html>
<head>
<style type="text/css">
html>body .canv { display: none }
.canv { filter: flipv() fliph(); writing-mode: tb-rl; width: 10px; height: 150px;
font-size:12px; font-family: Arial; background-color: white }
html>body .obj { display: block; width: 10px; height: 150px }
.obj { display: none }
</style>
</head>
<body>
<div class="canv">Hello!</div>
<object class="obj" type="image/svg+xml"
data="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'>
<text x='-150' y='10' font-family='Arial' font-size='12' transform='rotate(-90)'>Hello!</text>
</svg>">
</object>
</body>
</html>Замечательно работает во всех соврененных браузерах, но есть недостатки: Safari до сих пор не умеет масштабировать SVG вместе с текстом (а SVG — это вектор!), а FireFox, масштабируя SVG, не увеличивает размеры object. Задание размеров в «pt» ситуацию не исправило.
Тег «object» задан фиксированных размеров, если нужно изменить размер, то параметры «x» и «y» у текста внутри SVG нужно будет исправить (процедура пересчёта значений очевидна,
Конструкция «html>body» позволяет «прятать» CSS от Internet Explorer (включая седьмую версию), свойство
Detect SVG support
Искал код для проверки — поддерживает ли браузер SVG, так и не нашёл ничего подходящего. Написал свой, делюсь:
function DetectSVG()
{
if (navigator.mimeTypes != null && navigator.mimeTypes.length > 0)
return navigator.mimeTypes["image/svg-xml"] != null
var svg = 0
/*@cc_on
@if (@_jscript_version>4)
try { svg = 1; new ActiveXObject("Adobe.SVGCtl") }
catch (e) { return 0 }
@end
@cc_off @*/
return svg
}Первая половина кода проверяет наличие