Для векторной графики в Интернете формат SVG — самое то. Во-первых, он поддерживает масштабирование любой степени. Во-вторых, можно обращаться к любым составляющим элементам такой картинки — адресовать их, стилизовать и скриптовать. В-третьих, за исключением совсем маленьких файлов, этот формат выигрывает по компактности перед любыми растровыми представлениями, особенно если применить gzip-сжатие. В-четвёртых, сие есть стандарт W3C.
Но как поместить SVG-картинку в HTML-документ?
Известно, что есть три способа:
Первый сюрприз нам преподносит… угадайте, какой браузер? Ну, конечно, это IE не даёт скриптовать встроенную посредством тега
Второй сюрприз: не будет, пока мы не установим плагин — например, Adobe SVG Viewer. Правда, Adobe, вроде бы, прекратила его поддержку с 1 января 2009 г., но уже сделанного пока что должно хватить, да и, в конце концов, есть ещё RENESIS Player 1.0 for Internet Explorer и Ssrc SVG Plugin. Кроме того, как ни разобижена Microsoft за свой VML, с коим W3C её кинул в 1999 г., ввести нативную поддержку SVG её уламывают такие авторитеты как Google и Wikimedia Foundation. Обнадёживающая новость, что «Microsoft подала заявку на вступление в рабочую группу развития формата SVG в организации W3C» на Хабре уже обсуждалась. Так что тут есть все основания для оптимизма.
Далее. В описаниях тега
Не верьте! Это — третий сюрприз: в реальности IE игнорирует сей атрибут.
А чтобы заставить его работать, существует весьма малоизвестный (судя по тотальному отсутствию ссылок в тематических материалах в Интернете) хитрый способ с применением скриптов на JScript и VBScript. В принципе, ничего страшного, но об этом нужно знать.
Решение это, однако же, не вполне хорошо. Во-первых, оно не валидно, во-вторых, рассчитано на какие-то допотопные браузеры, коими уже никто не пользуется, но, в-третьих, не работает с современными браузерами (строго говоря, оно вообще не работает в том виде, в каком дано). Однако, основная идея решения верна, поэтому попытаемся сделать его работоспособным и современным.
Для начала, есть проблема вот с этой строчкой:
Функция в ней не выполняется, если только мы не перенесём её вызов на новую строчку. Только в XHTML экранирование будет выполняться ещё сложнее, посему вынесем-ка мы вызов функции во внешний скрипт:
Идём дальше. Нынешний код считает, что Firefox, Chrome и Safari для отображения SVG нуждаются в плагине, а Opera в этом отношении вообще безнадёжна. Однако, Opera имеет нативную поддержку SVG с версии 8.0 (19 апреля 2005 г.), Firefox — с версии 1.5 (30 ноября 2005 г.), Safari — с версии 3.0 (11 июня 2007 г.), а Chrome — с рождения (2 сентября 2008 г.). Фактически, все ухищрения нужны только для «Просмотрщика Интернета», сиречь Internet Explorer, у коего такая поддержка ожидается лишь в 9-й версии.
Тогда все три подключенных скрипта можно скрыть от прочих браузеров в условный комментарий (ну и насчёт языка перестаём притворяться, что это — JavaScript):
Там, где непосредственно подключается SVG-картинка мы можем заключить рекомендованный код в такой же комментарий, а следом написать что-нибудь такое:
В сумме получается довольно громоздкая конструкция, да ещё смешивающая представление с поведением. На самом деле можно просто написать:
А в подключаемом скрипте
Но HTML-код всё равно выглядит чрезмерно раздутым. Ведь условный комментарий с элементом
Укротим сперва скрипты. Будем цеплять к странице один скрипт
Наконец, от тяжеловесной конструкции на месте каждой картинки можно избавиться, если пожертвовать браузером IE с установленным SVG-плагином, но отключенным JScript. Я склонен решительно пожертвовать. Всем известно, насколько этот браузер требует костылей для соблюдения стандартов, так что если человек отключает в нём скрипты, он молчаливо соглашается видеть Интернет «условно».
Можно писать просто:
Впрочем, если кому-то вышеописанный вариант дорог, как память, можно и так:
Затем для IE мы должны подменять элемент
В заголовочной части страницы, как уже указано, пишем:
Файл
Содержимое
Скрипты
Google Chrome и Safari, однако, обнаруживают две проблемы. Для начала, они не обеспечивают пропорционального масштабирования SVG-картинки в общем случае. 4-е версии для этого требовали, чтобы у элемента
Вторая проблема серьёзней: если у вставленной через
Если использовать не
Увы, но на вставленных таким образом картинках перестают работать скрипты, так что решение не универсально!
Вот так. Только помним при стилизации и скриптовании, что в Firefox, Opera и, очевидно, IE 9 будет элемент
В передовых браузерах получение доступа из HTML-документа к SVG-документу тривиально. По событию
Проблемы возникают в Internet Explorer. В нём мы можем после загрузки страницы получить элемент
Кроме того, выяснилась ещё одна подлянка: содержимое таких элементов, как
Да и по спецификации, кстати, событие
Выход найден следующий (не очень элегантный, но… будем ещё думать!): событие
Ну, или, чтобы, уж, единообразно работало во всех браузерах:
Или даже просто (поскольку
В функции
Только следует иметь в виду, что работать с SVG-элементами средствами jQuery не получится (может быть, есть какой-то обходной маневр, но мне его раскопать или изобрести пока не удалось и лично я посчитал, что овчинка выделки не стоит). Дело в том, что его функции ожидают получить от метода
Два частных наблюдения по скриптованию SVG-документа. Во-первых, обнаружилось, что заданные в нём стили изменять скриптом не получается; всю динамику надо реализовывать через атрибуты (что, конечно, не очень правильно, если речь идёт об оформлении, к примеру, о цветовой заливке —
Забавно, что этот способ перестал работать локально в Chrome 5.0 из-за каких-то его заморочек с безопасностью. Совсем не забавно, что, как уже указано, в Webkit-браузерах он вообще не работает, если мы используем тег
SVG-графику рекомендуется подвергать gzip-сжатию. Оно и правильно, размер файла тогда может стать в три-четыре раза меньше. Если кому-то, как и мне, не хочется возиться с запускаемой из командной строки утилитой gzip, он может воспользоваться для этой цели не менее бесплатным, но наделённым графическим интерфейсом архиватором 7-Zip (в настройках архивирования обязательно выбрать метод Gzip!).
Заархивировали, сменив расширение с образующегося автоматически
Оказывается, виноват Apache. До сих пор (версия 2.2.12) он, в конфигурации по умолчанию, посылает браузеру требующийся для SVG-формата заголовок
Встречался мне ещё совет дописывать туда же (ради Firefox) следующее:
Возможно, это имеет смысл, если на сервере настроено автоматическое gzip-ование отдаваемых файлов; не знаю.
Недавно я имел по этому вопросу смешные бодания с техподдержкой своего хостера, кои продолжались месяц. Я так понял, что перед Apache там стоит фронт-ендом nginx, что неким образом ограничивает возможность использования директив Apache. Конкретнее, директива
работы директивы AddEncoding модуль Apache Mod_gzip», «За сжатие отвечает nginx, остальные директивы Apache поддерживаются в полном объёме» (неправда, кстати), «Приносим извинения. Передавать формат svgz можно лишь при наличии модуля mod_deflate, который, к сожалению, отсутствует на серверах, используемой Вами услуги» (и тут же предложение купить впятеро более дорогой план!). В конце концов, мне так и не объяснили, в чём у них закавыка, но сдались и стали отдавать правильный заголовок сами.
Но как поместить SVG-картинку в HTML-документ?
Как вставить SVG в HTML
Известно, что есть три способа:
- непосредственно в код (но — увы и ах! — IE этот способ не приемлет, да и остальные браузеры допускают лишь в XHTML-документе, что не всегда возможно);
- в плавающий фрейм
iframe
(это я даже пробовать не стал, считая фреймы устаревшим злом); - через тег
object
(вот этим приёмом и займёмся).
Первый сюрприз нам преподносит… угадайте, какой браузер? Ну, конечно, это IE не даёт скриптовать встроенную посредством тега
object
SVG-картинку и заливает белым её прозрачный фон! К счастью, он предоставляет свой проприетарный тег embed
для этих целей. Посредством условных комментариев и управлением стилями можно легко и валидно добиться, что нормальные браузеры будут отображать SVG через object
-элемент, а IE — через embed
. Но будет ли?Второй сюрприз: не будет, пока мы не установим плагин — например, Adobe SVG Viewer. Правда, Adobe, вроде бы, прекратила его поддержку с 1 января 2009 г., но уже сделанного пока что должно хватить, да и, в конце концов, есть ещё RENESIS Player 1.0 for Internet Explorer и Ssrc SVG Plugin. Кроме того, как ни разобижена Microsoft за свой VML, с коим W3C её кинул в 1999 г., ввести нативную поддержку SVG её уламывают такие авторитеты как Google и Wikimedia Foundation. Обнадёживающая новость, что «Microsoft подала заявку на вступление в рабочую группу развития формата SVG в организации W3C» на Хабре уже обсуждалась. Так что тут есть все основания для оптимизма.
Далее. В описаниях тега
embed
во множестве мест в Интернете можно прочитать, что у него есть такой замечательный атрибут pluginspage
, указывающий адрес, по коему, якобы, «будет направлен пользователь в том случае, если его браузер не поддерживает SVG-графику».Не верьте! Это — третий сюрприз: в реальности IE игнорирует сей атрибут.
А чтобы заставить его работать, существует весьма малоизвестный (судя по тотальному отсутствию ссылок в тематических материалах в Интернете) хитрый способ с применением скриптов на JScript и VBScript. В принципе, ничего страшного, но об этом нужно знать.
Модернизация решения Adobe
Решение это, однако же, не вполне хорошо. Во-первых, оно не валидно, во-вторых, рассчитано на какие-то допотопные браузеры, коими уже никто не пользуется, но, в-третьих, не работает с современными браузерами (строго говоря, оно вообще не работает в том виде, в каком дано). Однако, основная идея решения верна, поэтому попытаемся сделать его работоспособным и современным.
Для начала, есть проблема вот с этой строчкой:
<script language="JavaScript"><!-- checkAndGetSVGViewer(); // --> </script>
Функция в ней не выполняется, если только мы не перенесём её вызов на новую строчку. Только в XHTML экранирование будет выполняться ещё сложнее, посему вынесем-ка мы вызов функции во внешний скрипт:
<script language="JavaScript" src="viewSVJ.js"></script>
Идём дальше. Нынешний код считает, что Firefox, Chrome и Safari для отображения SVG нуждаются в плагине, а Opera в этом отношении вообще безнадёжна. Однако, Opera имеет нативную поддержку SVG с версии 8.0 (19 апреля 2005 г.), Firefox — с версии 1.5 (30 ноября 2005 г.), Safari — с версии 3.0 (11 июня 2007 г.), а Chrome — с рождения (2 сентября 2008 г.). Фактически, все ухищрения нужны только для «Просмотрщика Интернета», сиречь Internet Explorer, у коего такая поддержка ожидается лишь в 9-й версии.
Тогда все три подключенных скрипта можно скрыть от прочих браузеров в условный комментарий (ну и насчёт языка перестаём притворяться, что это — JavaScript):
<!--[if IE]>
<script language="JScript" src="svgcheck.js"></script>
<script language="VBScript" src="svgcheck.vbs"></script>
<script language="JScript" src="viewSVJ.js"></script>
<![endif]-->
Там, где непосредственно подключается SVG-картинка мы можем заключить рекомендованный код в такой же комментарий, а следом написать что-нибудь такое:
<!--[if !IE]>-->
<object type="image/svg+xml" data="hello.svg" height="200" width="600"></object>
<!--<![endif]-->
В сумме получается довольно громоздкая конструкция, да ещё смешивающая представление с поведением. На самом деле можно просто написать:
<!--[if IE]>
<embed src="hello.svg" height="100" width="100" type="image/svg-xml" pluginspage="http://www.adobe.com/svg/viewer/install/">
<![endif]-->
<!--[if !IE]>-->
<object type="image/svg+xml" data="hello.svg" height="100" width="100"></object>
<!--<![endif]-->
А в подключаемом скрипте
viewSVJ.js
, если SVG-плагин всё-таки не установлен, будем перебирать элементы embed
и заменять их на предупреждения со ссылками:checkAndGetSVGViewer();
window.attachEvent(
"onload",
function(){
if(window.svgInstalled)//если SVG-плагин установлен
return;
var embeds=document.getElementsByTagName("embed");
for(var embedNumber=0, embedTypeAttr; embedNumber<embeds.length; embednumber++){
embedtypeattr=embeds[embedNumber].attributes["type"];
if(embedtypeattr="image/svg-xml" /*MSIE 5*/ || embedtypeattr.value="image/svg-xml")
embeds[embednumber].outerhtml="<p>To view this page you need an SVG viewer. <a href=\""+getSVGInstallPage()+"\">Click here</a> for more information.</p>";
}
}
);
Но HTML-код всё равно выглядит чрезмерно раздутым. Ведь условный комментарий с элементом
embed
надо писать для каждой SVG-картинки, а ссылки на несколько скриптов (и тоже с условным комментарием) — для каждой содержащей их страницы! Конечно, существует шаблонизация, но… Вдобавок, эти скрипты замусоривают глобальное пространство имён, а лезть разбираться в их устаревший код не хочется.Укротим сперва скрипты. Будем цеплять к странице один скрипт
fixSVG.js
, где для IE напишем свою ветку, в которой будем подгружать в динамически созданный плавающий фрейм (да, я фыркал по их адресу, но это же решение для браузера, который пока лучшего и не заслужил!) скрипты от «Эдоуби» (Adobe); выполнять с их помощью проверку на наличие установленного SVG-плагина; если он не установлен, подменять картинки на соответствующие уведомления со ссылкой; и, наконец, удалять этот фрейм (чистоты страницы ради). Детали реализации смотрим ниже.Наконец, от тяжеловесной конструкции на месте каждой картинки можно избавиться, если пожертвовать браузером IE с установленным SVG-плагином, но отключенным JScript. Я склонен решительно пожертвовать. Всем известно, насколько этот браузер требует костылей для соблюдения стандартов, так что если человек отключает в нём скрипты, он молчаливо соглашается видеть Интернет «условно».
Можно писать просто:
<object type="image/svg+xml" data="hello.svg"></object>
Впрочем, если кому-то вышеописанный вариант дорог, как память, можно и так:
<object type="image/svg+xml" data="hello.svg">Для просмотра этой страницы нужен <a href="http://www.adobe.com/svg/viewer/install/">SVG viewer</a>.</object>
Затем для IE мы должны подменять элемент
object
на элемент embed
, если SVG-плагин установлен, и на уведомление со ссылкой, если он ещё не установлен.В заголовочной части страницы, как уже указано, пишем:
<script type="text/ecmascript" src="fixSVG.js"></script>
Файл
fixSVG.js
выглядит так (с использованием уже скриптового условного комментария):/*@cc_on
if(@_jscript_version<9)
window.attachEvent(
"onload",
function(){
var iframe=document.createElement("iframe");
iframe.src="js/fixSVG_IE_5-8.html";
document.body.appendChild(iframe);
}
);
@*/
Содержимое
fixSVG_IE_5-8.html
, подгружающееся в динамически созданный плавающий фрейм:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Fix SVG for IE 5-8</title>
<script type="text/jscript" src="svgcheck.js"></script>
<script type="text/vbscript" src="svgcheck.vbs"></script>
<script type="text/jscript" src="checkSVGViewer.js"></script>
</head>
<body></body>
</html>
Скрипты
svgcheck.js
и svgcheck.vbs
— адоубивские, нетронутые. А fixSVG_IE_5-8.js
— наш:checkAndGetSVGViewer();//проверяем наличие SVG-плагина
if(window.svgInstalled){
var objects=window.parent.document.getElementsByTagName("object");
for(var objectNumber=objects.length, objectNode, objectTypeAttr, embedNode, codebase, attrNumber, attrNode; objectNumber--;){
objectNode=objects[objectNumber];
objectTypeAttr=objectNode.attributes["type"];
if(objectTypeAttr=="image/svg+xml" || objectTypeAttr.value=="image/svg+xml"){
embedNode=window.parent.document.createElement("embed");
embedNode.setAttribute("type", "image/svg-xml");
embedNode.setAttribute("pluginspage", "http://www.adobe.com/svg/viewer/install/");
embedNode.setAttribute("wmode", "transparent");//обеспечиваем прозрачность фона
codebase=objectNode.getAttribute("codebase");
embedNode.setAttribute("src", ((null===codebase)?"":codebase)+objectNode.getAttribute("data"));
for(attrNumber=objectNode.attributes.length; attrNumber--;){
attrNode=objectNode.attributes[attrNumber];
if(//сюрприз! IE не поддерживает indexOf!
attrNode.name!="archive" &&
attrNode.name!="classid" &&
attrNode.name!="codebase" &&
attrNode.name!="codetype" &&
attrNode.name!="data" &&
attrNode.name!="declare" &&
attrNode.name!="standby" &&
attrNode.name!="tabindex" &&
attrNode.name!="type" &&
attrNode.name!="usemap"
)
embedNode.setAttribute(attrNode.name, attrNode.value);
}
objectNode.parentNode.replaceChild(embedNode, objectNode);
}
}
}
else
if(window.svgViewerAvailable){//для проформы (мы знаем, что для IE 5-8 такой плагин есть!)
var message;
switch(navigator.browserLanguage.substr(0,2)){
case "ru":
message="Для просмотра этой страницы нужен";
break;
case "en":
default:
message="To view this page you need an";
}
var objects=window.parent.document.getElementsByTagName("object");
for(var objectNumber=objects.length, objectTypeAttr; objectNumber--;){
objectTypeAttr=objects[objectNumber].attributes["type"];//objects[objectNumber].getAttribute("type")===null!
if(objectTypeAttr=="image/svg+xml" || objectTypeAttr.value=="image/svg+xml")//тут учтён IE5
objects[objectNumber].outerHTML="<p>"+message+" <a href=\""+getSVGInstallPage()+"\">SVG viewer</a>.</p>";
}
}
window.frameElement.parentNode.removeChild(window.frameElement);//удаляем плавающий фрейм, вызвавший этот скрипт
SVG-графика в Webkit-браузерах
Google Chrome и Safari, однако, обнаруживают две проблемы. Для начала, они не обеспечивают пропорционального масштабирования SVG-картинки в общем случае. 4-е версии для этого требовали, чтобы у элемента
svg
были заданы атрибуты width
и height
, а 5-е, напротив, чтобы они не были заданы! Но и при этом масштабирование получается не вполне удовлетворительное.Вторая проблема серьёзней: если у вставленной через
object
SVG-картинки прозрачный фон, он заливается белым (это баг! причём очень старый, более чем двухлетней давности — и в 5-х версиях этих браузеров он не исправлен), как и в IE (но там мы можем просто добавить embed
-элементу атрибут wmode
со значением transparent
).Если использовать не
object
, а img
, то всё отлично, но Firefox пока что такого способа вставки SVG-картинки не понимает. Поэтому пишем в вышеупомянутый файл fixSVG.js
скрипт для Webkit-браузеров (смирившись с белым фоном в ненормальной ситуации отключенного Javascript), подменяющий в загруженном документе object
с SVG-картинкой на img
:if(/AppleWebKit/.test(navigator.userAgent))
window.addEventListener(
"load",
function(){
var objects=document.getElementsByTagName("object");
for(var objectNumber=objects.length, objectNode, codebase, imageNode, attrNumber, attrNode; objectNumber--;){
objectNode=objects[objectNumber];
if(objectNode.getAttribute("type")==="image/svg+xml"){
imageNode=document.createElement("img");
codebase=objectNode.getAttribute("codebase");
imageNode.setAttribute("src", ((null===codebase)?"":codebase)+objectNode.getAttribute("data"));
imageNode.setAttribute("alt", "SVG");//совсем без alt нельзя по стандарту HTML
for(attrNumber=objectNode.attributes.length; attrNumber--;){
attrNode=objectNode.attributes[attrNumber];
if(-1===["declare", "classid", "codebase", "data", "type", "codetype", "archive", "standby", "tabindex"].indexOf(attrNode.name))
imageNode.setAttribute(attrNode.name, attrNode.value);
}
objectNode.parentNode.replaceChild(imageNode, objectNode);
}
}
},
false
);
Увы, но на вставленных таким образом картинках перестают работать скрипты, так что решение не универсально!
Вот так. Только помним при стилизации и скриптовании, что в Firefox, Opera и, очевидно, IE 9 будет элемент
object
, в Safari и Google Chrome (надеюсь, когда-нибудь везде) — img
, а в IE 5—8 — embed
.Скриптование внедрённой SVG-картинки
В передовых браузерах получение доступа из HTML-документа к SVG-документу тривиально. По событию
load
нам оказывается доступен элемент object
, на него тоже можно навесить событие load
и в его обработчике мы замечательным образом получим искомое. Посредством jQuery это можно было бы сделать примерно так:$(
function(){
$("object#SceletonObject").load(
function(){
var SVGDocument=$(this)[0].getSVGDocument();
…
}
);
}
);
Проблемы возникают в Internet Explorer. В нём мы можем после загрузки страницы получить элемент
embed
и у него даже уже доступен SVG-документ, но только — вот беда! — он совершенно пуст. Навесить на элемент embed
событие load
мне не удалось; похоже, оно вообще не поддерживается (впрочем, те из якобы поддерживаемых событий, что я пробовал, тоже не работают).Кроме того, выяснилась ещё одна подлянка: содержимое таких элементов, как
object
и embed
загружается асинхронно, в отдельном потоке. Это означает, как я понимаю, что, с одной стороны, пока не закончен парсинг основной страницы, элемент ещё недоступен для навешивания на него обработчика события, а когда он закончен — событие загрузки элемента может уже сработать и тогда обработчик навешивать уже бесполезно. Кажется, именно последний случай я периодически наблюдал в экспериментах, не улавливая никакой закономерности в глюке.Да и по спецификации, кстати, событие
load
у элемента object
отсутствует — оно есть в HTML только у элемента body
. Так что то, что оно вообще где-то работает — это неправильно!Выход найден следующий (не очень элегантный, но… будем ещё думать!): событие
load
пишем внутри SVG-кода у элемента svg
, вызывая оттуда функцию HTML-документа. Как-нибудь так:<svg xmlns="http://www.w3.org/2000/svg" onload="InitSVG(document);">
Ну, или, чтобы, уж, единообразно работало во всех браузерах:
<svg xmlns="http://www.w3.org/2000/svg" onload="if('InitSVG' in window) InitSVG(document); else parent.InitSVG(document);">
Или даже просто (поскольку
parent
в окне верхнего уровня указывает на само это окно):<svg xmlns="http://www.w3.org/2000/svg" onload="parent.InitSVG(document);">
В функции
InitSVG
мы уже можем получить SVG-документ и из него — все его элементы. Лепота!Только следует иметь в виду, что работать с SVG-элементами средствами jQuery не получится (может быть, есть какой-то обходной маневр, но мне его раскопать или изобрести пока не удалось и лично я посчитал, что овчинка выделки не стоит). Дело в том, что его функции ожидают получить от метода
getElementsByTagName
результат типа HTMLCollection
, из коего можно отбирать элементы по индексу, как из обычного массива. А тут мы получим (везде, кроме Firefox) результат типа NodeList
, из коего элемент можно будет выцепить только посредством особого метода item(индекс)
. Фреймворк на такое не рассчитывает и обламывается (во всяком случае, так было осенью, когда я с этим экспериментировал). Так что придётся работать непосредственно с DOM-методами, держа кроссбраузерность в уме. Сие напряжно, но возможно.Два частных наблюдения по скриптованию SVG-документа. Во-первых, обнаружилось, что заданные в нём стили изменять скриптом не получается; всю динамику надо реализовывать через атрибуты (что, конечно, не очень правильно, если речь идёт об оформлении, к примеру, о цветовой заливке —
fill
). Во-вторых, если у SVG-элемента не стоит никакой заливки, то события mouseover
и mouseout
срабатывают только на рамке и вполне могут не успеть сработать вообще (к счастью, можно прописать атрибут fill
один раз у элемента-предка и он пронаследуется).Забавно, что этот способ перестал работать локально в Chrome 5.0 из-за каких-то его заморочек с безопасностью. Совсем не забавно, что, как уже указано, в Webkit-браузерах он вообще не работает, если мы используем тег
img
.Как отдавать с сервера SVGZ
SVG-графику рекомендуется подвергать gzip-сжатию. Оно и правильно, размер файла тогда может стать в три-четыре раза меньше. Если кому-то, как и мне, не хочется возиться с запускаемой из командной строки утилитой gzip, он может воспользоваться для этой цели не менее бесплатным, но наделённым графическим интерфейсом архиватором 7-Zip (в настройках архивирования обязательно выбрать метод Gzip!).
Заархивировали, сменив расширение с образующегося автоматически
.svg.gz
на .svgz
, после чего с изумлением убеждаемся, что получившийся файл адекватно воспринимают только Opera и Internet Explorer, а Firefox, Safari и Chrome воротят нос, ругаясь на синтаксис XML. Ну, конечно, какой там XML, пока не разархивируешь? А почему, собственно, они не разархивируют?Оказывается, виноват Apache. До сих пор (версия 2.2.12) он, в конфигурации по умолчанию, посылает браузеру требующийся для SVG-формата заголовок
Content-Type: image/svg+xml
, но не требующийся для его gzip-ованной версии заголовок Content-Encoding: gzip
. Посему лезем исправлять в конфигурацию сервера или просто пишем в файл .htaccess строчку «AddEncoding gzip .svgz
».Встречался мне ещё совет дописывать туда же (ради Firefox) следующее:
<FilesMatch \.svgz$>
<IfModule mod_gzip.c>
mod_gzip_on No
</IfModule>
</FilesMatch>
Возможно, это имеет смысл, если на сервере настроено автоматическое gzip-ование отдаваемых файлов; не знаю.
Недавно я имел по этому вопросу смешные бодания с техподдержкой своего хостера, кои продолжались месяц. Я так понял, что перед Apache там стоит фронт-ендом nginx, что неким образом ограничивает возможность использования директив Apache. Конкретнее, директива
AddType
срабатывает, а AddEncoding
— нет. Разумеется, раздел «Помощь» на сайте провайдера не содержит про эту закавыку ни слова и даже вообще ни единого упоминания про nginx. Техподдержка упорно не хотела мне внимать и выдавать свои тайны, потчуя меня безумными отписками: «Заголовок не отдается, поскольку на сервере не установлен необходимый дляработы директивы AddEncoding модуль Apache Mod_gzip», «За сжатие отвечает nginx, остальные директивы Apache поддерживаются в полном объёме» (неправда, кстати), «Приносим извинения. Передавать формат svgz можно лишь при наличии модуля mod_deflate, который, к сожалению, отсутствует на серверах, используемой Вами услуги» (и тут же предложение купить впятеро более дорогой план!). В конце концов, мне так и не объяснили, в чём у них закавыка, но сдались и стали отдавать правильный заголовок сами.