Внедрение SVG в HTML.

08.07.2019

Это сам Q & A из удобного кода, с которым я пришел.

В настоящее время нет простого способа встраивания SVG-изображения, а затем доступ к элементам SVG через CSS. Существуют различные методы использования JS SVG-фреймворков, но они слишком сложны, если все, что вы делаете, это простой значок с состоянием опрокидывания.

Итак, вот что я придумал, и я считаю, что это самый простой способ использовать SVG файлы на веб-сайте. Он берет свою концепцию из ранних методов замены текста на изображение, но, насколько мне известно, никогда не было сделано для SVG.

Это вопрос:

17 ответов

Во-первых, используйте тег IMG в своем HTML, чтобы вставить SVG-графику. Я использовал Adobe Illustrator, чтобы сделать графику.

Это похоже на то, как вы вставляете обычный образ. Обратите внимание, что вам нужно установить IMG для класса svg. Класс "social-link" просто для примера. Идентификатор не требуется, но полезен.

Затем используйте этот код jQuery (в отдельном файле или встроенном в HEAD).

/* * Replace all SVG images with inline SVG */ jQuery("img.svg").each(function(){ var $img = jQuery(this); var imgID = $img.attr("id"); var imgClass = $img.attr("class"); var imgURL = $img.attr("src"); jQuery.get(imgURL, function(data) { // Get the SVG tag, ignore the rest var $svg = jQuery(data).find("svg"); // Add replaced image ID to the new SVG if(typeof imgID !== "undefined") { $svg = $svg.attr("id", imgID); } // Add replaced image classes to the new SVG if(typeof imgClass !== "undefined") { $svg = $svg.attr("class", imgClass+" replaced-svg"); } // Remove any invalid XML tags as per http://validator.w3.org $svg = $svg.removeAttr("xmlns:a"); // Replace image with new SVG $img.replaceWith($svg); }, "xml"); });

Что делает вышеприведенный код, это искать все IMG с классом "svg" и заменять его встроенным SVG из связанного файла. Массивным преимуществом является то, что он позволяет использовать CSS для изменения цвета SVG сейчас, например:

Svg:hover path { fill: red; }

Код jQuery я написал также порты по исходному идентификатору и классам изображений. Итак, этот CSS тоже работает:

#facebook-logo:hover path { fill: red; }

Social-link:hover path { fill: red; }

Svg path { fill: #000; }

$(document).ready(function() { $("img").each(function() { var $img = jQuery(this); var imgURL = $img.attr("src"); var attributes = $img.prop("attributes"); $.get(imgURL, function(data) { // Get the SVG tag, ignore the rest var $svg = jQuery(data).find("svg"); // Remove any invalid XML tags $svg = $svg.removeAttr("xmlns:a"); // Loop through IMG attributes and apply on SVG $.each(attributes, function() { $svg.attr(this.name, this.value); }); // Replace IMG with SVG $img.replaceWith($svg); }, "xml"); }); });

Если вы можете включить в свою версию файлы (включая PHP или включить через ваш CMS), вы можете добавить SVG-код и включить его на свою страницу. Это работает так же, как вставка источника SVG на страницу, но делает очистку страницы более чистым.

Преимущество состоит в том, что вы можете нацелить части своего SVG с помощью CSS для зависания - не требуется javascript.

Вам просто нужно использовать правило CSS следующим образом:

#pathidorclass:hover { fill: #303 !important; }

Обратите внимание, что бит!important необходим для переопределения цвета заливки.

Теперь вы можете использовать свойство filter CSS в большинстве современных браузеров (включая Edge, но не IE11). Он работает с изображениями SVG, а также с другими элементами. Вы можете использовать hue-rotate или invert для изменения цветов, хотя они не позволяют изменять разные цвета независимо друг от друга. Я использую следующий класс CSS, чтобы показать "отключенную" версию значка (где оригинал представляет собой изображение SVG с насыщенным цветом):

Disabled { opacity: 0.4; filter: grayscale(100%); -webkit-filter: grayscale(100%); }

Это делает его светло-серым в большинстве браузеров. В IE (и, возможно, Opera Mini, который я не тестировал), он заметно угасает с помощью свойства непрозрачности, которое по-прежнему выглядит довольно хорошо, хотя оно не серое.

Здесь приведен пример с четырьмя различными классами CSS для значка колокола Twemoji : оригинал (желтый), вышеперечисленный класс "отключен", hue-rotate (зеленый) и invert (синий).

Twa-bell { background-image: url("https://twemoji.maxcdn.com/svg/1f514.svg"); display: inline-block; background-repeat: no-repeat; background-position: center center; height: 3em; width: 3em; margin: 0 0.15em 0 0.3em; vertical-align: -0.3em; background-size: 3em 3em; } .grey-out { opacity: 0.4; filter: grayscale(100%); -webkit-filter: grayscale(100%); } .hue-rotate { filter: hue-rotate(90deg); -webkit-filter: hue-rotate(90deg); } .invert { filter: invert(100%); -webkit-filter: invert(100%); }

@Drew Baker дал отличное решение для решения проблемы. Код работает правильно. Тем не менее, те, кто использует AngularJs, могут найти большую зависимость от jQuery. Следовательно, я подумал, что неплохо вставить для пользователей AngularJS код, следующий за решением @Drew Baker.

Метод AngularJs одного и того же кода

1. Html: используйте тег ниже в файле html:

2. Директива: это будет директива о том, что вам нужно будет распознать тег:

"use strict"; angular.module("myApp") .directive("svgImage", ["$http", function($http) { return { restrict: "E", link: function(scope, element) { var imgURL = element.attr("src"); // if you want to use ng-include, then // instead of the above line write the bellow: // var imgURL = element.attr("ng-include"); var request = $http.get(imgURL, {"Content-Type": "application/xml"}); scope.manipulateImgNode = function(data, elem){ var $svg = angular.element(data); var imgClass = elem.attr("class"); if(typeof(imgClass) !== "undefined") { var classes = imgClass.split(" "); for(var i = 0; i < classes.length; ++i){ $svg.classList.add(classes[i]); } } $svg.removeAttribute("xmlns:a"); return $svg; }; request.success(function(data){ element.replaceWith(scope.manipulateImgNode(data, element)); }); } }; }]);

Any-class-you-wish{ border: 1px solid red; height: 300px; width: 120px }

4. Единичный тест с карма-жасмином:

"use strict"; describe("Directive: svgImage", function() { var $rootScope, $compile, element, scope, $httpBackend, apiUrl, data; beforeEach(function() { module("myApp"); inject(function($injector) { $rootScope = $injector.get("$rootScope"); $compile = $injector.get("$compile"); $httpBackend = $injector.get("$httpBackend"); apiUrl = $injector.get("apiUrl"); }); scope = $rootScope.$new(); element = angular.element(""); element = $compile(element)(scope); spyOn(scope, "manipulateImgNode").andCallThrough(); $httpBackend.whenGET(apiUrl + "me").respond(200, {}); data = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; $httpBackend.expectGET("/icons/icon-man.svg").respond(200, data); }); afterEach(function() { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); it("should call manipulateImgNode atleast once", function () { $httpBackend.flush(); expect(scope.manipulateImgNode.callCount).toBe(1); }); it("should return correct result", function () { $httpBackend.flush(); var result = scope.manipulateImgNode(data, element); expect(result).toBeDefined(); }); it("should define classes", function () { $httpBackend.flush(); var result = scope.manipulateImgNode(data, element); var classList = ["svg"]; expect(result.classList).toBe(classList); }); });

Я понимаю, что вы хотите выполнить это с помощью CSS, но просто напоминание на случай, если это маленький, простой образ - вы всегда можете открыть его в Notepad++ и изменить путь /whatelement fill:

Это могло бы сэкономить массу уродливого сценария. Извините, если это вне базы, но иногда простые решения можно упустить.

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

Я написал директиву для решения этой проблемы с помощью AngularJS. Доступно .

Он заменяет элемент SVG после его рендеринга и помещает его внутри элемента div , что делает его CSS легко изменчивым. Это помогает использовать один и тот же файл SVG в разных местах, используя разные размеры/цвета.

Использование прост:

После этого вы можете легко:

Svg-class svg { fill: red; // whichever color you want }

Здесь нет кода рамки, только чистый js:

Document.querySelectorAll("img.svg").forEach(function(element) { var imgID = element.getAttribute("id") var imgClass = element.getAttribute("class") var imgURL = element.getAttribute("src") xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { var svg = xhr.responseXML.getElementsByTagName("svg"); if(imgID != null) { svg.setAttribute("id", imgID); } if(imgClass != null) { svg.setAttribute("class", imgClass + " replaced-svg"); } svg.removeAttribute("xmlns:a") if(!svg.hasAttribute("viewBox") && svg.hasAttribute("height") && svg.hasAttribute("width")) { svg.setAttribute("viewBox", "0 0 " + svg.getAttribute("height") + " " + svg.getAttribute("width")) } element.parentElement.replaceChild(svg, element) } } xhr.open("GET", imgURL, true) xhr.send(null) })

Здесь версия для knockout.js на основе принятого ответа:

Важно: Это действительно требует jQuery для замены, но я подумал, что это может быть полезно для некоторых.

Ko.bindingHandlers.svgConvert = { "init": function () { return { "controlsDescendantBindings": true }; }, "update": function (element, valueAccessor, allBindings, viewModel, bindingContext) { var $img = $(element); var imgID = $img.attr("id"); var imgClass = $img.attr("class"); var imgURL = $img.attr("src"); $.get(imgURL, function (data) { // Get the SVG tag, ignore the rest var $svg = $(data).find("svg"); // Add replaced image ID to the new SVG if (typeof imgID !== "undefined") { $svg = $svg.attr("id", imgID); } // Add replaced image classes to the new SVG if (typeof imgClass !== "undefined") { $svg = $svg.attr("class", imgClass + " replaced-svg"); } // Remove any invalid XML tags as per http://validator.w3.org $svg = $svg.removeAttr("xmlns:a"); // Replace image with new SVG $img.replaceWith($svg); }, "xml"); } };

Затем просто примените data-bind="svgConvert: true" к вашему тегу img.

Это решение полностью заменяет тег img SVG, и любые дополнительные привязки не будут соблюдаться.

Существует библиотека с открытым исходным кодом под названием SVGInject, которая использует атрибут onload для запуска инъекции. Проект GitHub можно найти на странице https://github.com/iconfu/svg-inject

Ниже приведен минимальный пример использования SVGInject:

После загрузки изображения onload="SVGInject(this) вызовет инъекцию, а элемент будет заменен содержимым SVG файла, указанного в атрибуте src .

Он решает несколько проблем с инъекцией SVG:

SVG можно скрыть до завершения инъекции. Это важно, если стиль уже применяется во время загрузки, что в противном случае могло бы привести к кратковременной "вспышке без использования содержимого".

Элементы автоматически внедряют их. Если вы добавляете SVG динамически, вам не придется беспокоиться о вызове функции впрыска снова.

Случайная строка добавляется к каждому идентификатору в SVG, чтобы избежать повторения одного и того же ID в документе, если SVG вводится несколько раз.

SVGInject - это простой Javascript и работает со всеми браузерами, поддерживающими SVG.

Если у нас есть большее количество таких svg-изображений, мы также можем воспользоваться файлами-шрифтами.
Такие сайты, как https://glyphter.com/ , могут получить файл шрифтов из наших svgs.

например.

@font-face { font-family: "iconFont"; src: url("iconFont.eot"); } #target{ color: white; font-size:96px; font-family:iconFont; }

Поскольку SVG - это в основном код, вам нужно просто содержимое. Я использовал PHP для получения контента, но вы можете использовать все, что захотите.

Затем я печатал содержимое "как есть" внутри контейнера div

Чтобы финализировать правило для контейнеров SVG childs на CSS

Fill-class > svg { fill: orange; }

Я получил эти результаты с помощью значка материала SVG:

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

/** * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents. * * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element). * * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object"s * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place * any styles in a style class instead. */ (function ($) { $.fn.svgLoader = function () { var src = $(this).attr("src"); var width = this.attr("width"); var height = this.attr("height"); var cls = this.attr("class"); var ctx = $(this); // Get the svg file and replace the element. $.ajax({ url: src, cache: false }).done(function (html) { let svg = $(html); svg.attr("width", width); svg.attr("height", height); svg.attr("class", cls); var newHtml = $("").append(svg.clone()).html(); ctx.replaceWith(newHtml); }); return this; }; }(jQuery));

В html укажите элемент svg следующим образом.

SVG представляет собой формат изображения для векторной графики. В буквальном смысле это ни что иное, как масштабируемая векторная графика. То есть это как раз то, с чем вы работаете в Adobe Illustrator. Использовать SVG при web-разработке довольно легко, но есть особенности, которые стоит рассмотреть.

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

Нарисуем что-нибудь для предстоящей работы в Adobe Illustrator. Возьмём птичку Kiwi:

Обратите внимание, что холст обрезается ровно по краю картинки. Холст в SVG абсолютно идентично строится, как PNG или JPG. Вы можете сохранить файл непосредственно из Adobe Illustrator как SVG файл.

После того, как вы сохраните файл, появится еще одно диалоговое окно с опциями SVG. Честно говоря, я не очень много знаю о всех представленных в этом окне настройках. Существует спецификация SVG профилей, так что, если вам интересно можете почитать. Я считаю, что SVG 1.1 работает отлично.

Самое интересное здесь то, что вы можете либо нажать ОК и сохранить файл, или нажать кнопку “SVG Code…” и откроется текстовый редактор с кодом SVG.

Оба способа могут оказаться полезными.

Используем SVG в виде тега img

В Illustrator наш холст получился 612px ✕ 502px.

Насколько большим изображение будет на страницу решать вам. Вы можете изменить размер изображения путем определения свойств width и height, то есть абсолютно так же, как и с PNG или JPG. Вот пример:

Check out this Pen!

Как сделать кроссбраузерный SVG

Используя SVG таким образом, нужно иметь ввиду о разной поддержки браузерами. По сути, SVG работает везде кроме IE8 и нижу, а также Android 2.3 и ниже.

Если вам необходимо использовать SVG, но также нужна поддержка вышеперечисленных браузеров, есть несколько вариантов решения проблемы. Я использовал несколько техник в различных проектах для решения этой проблемы.

Одним из способов, чтобы проверить поддержку SVG является Modernizr, с помощью которого меняется путь src:

If (!Modernizr.svg) { $(".logo img").attr("src", "images/logo.png"); }

David Bushell придумал очень легкий альтернативный способ, но он содержит javascript в разметке:

Также может помочь сервис SVGeezy. По ходу продолжения этой статьи мы разберём много различных резервных методов для поддержки SVG.

Использование SVG в качестве фона background-image

По аналогии с тегом img, SVG можно использовать в качестве фонового изображения:

Kiwi Corp .logo { display: block; text-indent: -9999px; width: 100px; height: 82px; background: url(kiwi.svg); background-size: 100px 82px; }

Обратите внимание, мы устанавливаем background-size точно таким же, как и размер элемента. Это необходимо сделать, так как в противном случае мы бы увидели небольшую верхнюю часть оригинального изображения. Эти цифры учитывают оригинальные пропорции изображения. Вы также можете использовать в качестве значений background-size ключевые слова, например contain, чтобы изображение полностью занимало весь элемент.

Использование SVG в качестве фонового изображения накладывает свой отпечаток на браузерную поддержку, но вцелом, всё аналогично, как и при использовании тега img.

Modernizr может помочь нам здесь еще более эффективным способом, чем в случае с img. Дело в том, если заменить фоновое изображение с поддерживаемым форматом, то будет выполнен лишь один HTTP запрос вместо двух, как в случае с img. Modernizr добавляет имя класса “no-svg” к тегу HTML, если браузер не имеет поддержки SVG:

Main-header { background: url(logo.svg) no-repeat top left; background-size: contain; } .no-svg .main-header { background-image: url(logo.png); }

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

Использование “inline” SVG

Выше упоминалось, что при сохранении картинки в формате SVG, с помощью редактора Illustrator можно получить правильный SVG код (также можно отрыть файл с помощью текстового редактора и скопировать этот код). Вы можете скопировать этот код в ваш HTML и SVG будет отображаться абсолютно также, как при использовании img.

Это может быть полезным, так как образ изображения приходит вместе с кодом в документ и при этом не осуществляется HTTP запрос. Другими словами, преимущества такие же, как при использовании данных Data URI. Однако, недостатки тоже есть. Из-за вставки вставки прямого кода SVG, документ начинает быть похож на большой раздутый кусок дерьма.

Также есть вариант для вставки SVG на стороне сервера:

Оптимизация SVG

Adobe Illustrator не производит по умолчанию действия по оптимизации получаемого SVG изображения. Он предоставляет DOCTYPE и заметки, и всё это по большому счёту мусор. SVG по умолчанию имеет довольно небольшой вес, но почему бы не сделать его ещё меньше? Peter Collingridge предоставил онлайн инструмент для оптимизации SVG Optimiser. С помощью этого сервиса вы можете закачать старый файл и получить оптимизированный новый.

Если хотите больше хардкора – без проблем, вот инструмент для оптимизации SVG с помощью серверного javascript Node JS tool https://github.com/svg/svgo

Стилевое оформление SVG

Видите, как SVG похож на HTML? Это потому что они оба являются данными XML. В нашем дизайне есть два элемента, которые составляют основу, это ellipse и path. Мы можем без проблем указать им классы через HTML код.

Сейчас мы можем контролировать эти элементы с помощью специального SVG CSS. Этот CSS не должен напрямую встраиваться в SVG, он может быть расположен абсолютно в любом месте. Обратите внимание, что SVG элементы имеют специальный набор стилей, которые созданы специально для работы с векторной графикой. Например, используется не обычный background-color, а fill. Хотя некоторые обычные стили также работают, например:hover.

Kiwi { fill: #94d31b; } .kiwi:hover { fill: #ace63c; }

В SVG имеются забавные фильтры. Например размытие:

...

Затем вы можете при необходимости применить это в css:

Ground:hover { filter: url(#pictureFilter); }

Вот, что получилось:

Check out this Pen!

Поддержка “inline” SVG браузерами

Список браузеров, поддерживающих данный режим отображения SVG можно посмотреть здесь http://caniuse.com/#feat=svg-html5. Опять же, поддержки нет в IE8 и Android 2.3.

Один из вариантов фолбэка для такого типа SVG:

...

Затем снова используем Modernizr:

Logo-fallback { display: none; /* Make sure it"s the same size as the SVG takes up */ } .no-svg .logo-fallback { background-image: url(logo.png); }

Использование SVG в качестве объекта object

Если использование “inline” SVG вам не по душе (помните, что у этого варианта есть недостатки, например отсутствие кеширования), вы можете связать SVG с объектом object и потом менять его с помощью css:

Для кроссбраузерной поддержки используем Modernizr:

No-svg .logo { width: 200px; height: 164px; background-image: url(kiwi.png); }

Этот вариант отлично работает с кешированием и имеет самую большую поддержку браузерами, чем все вышеперечисленные. Но, чтобы подействовать с помощью CSS на такой объект, придётся прописывать стили непосредственно в SVG файл.

...

Использование Data URI вялется способом уменьшения веса SVG. Mobilefish.com предоствляет онлайн инструмент оптимизации для этой цели. Достаточно вставить содержимое вашего SVG файла и заполнить форму, далее результат будет отображён в текстовом поле, который можно скопировать. Выглядит это так:

Вы можете использовать этот код где угодно! Нпример:

Logo { background: url(data:image/svg+xml;base64,); }

И кстати, если у вас есть встроенные style в SVG, который находится до base64, он будет работать, если вы используете его, как object!

  • Tutorial

Нам нужно:

  • Установить на сайте собственные иконки с помощью SVG.
  • Они должны управляться с помощью CSS (форма, размер, заливка, эффекты в том числе и их поведение).
  • Они должны иметь маленький вес и находиться в одном месте для экономии http запросов.
  • Работать во всех основных современных браузерах.
  • демо Зачем я это пишу? Несмотря на растущую популярность вектора в браузере, его возраст и поддержку браузерами , хороших решений использования, как кажется мне, очень мало. Позвольте объясниться. Конечно о SVG много писали и рассказывали . Даже о SVG и CSS вместе. Но когда я столкнулся с необходимостью сделать SVG иконки для сайта, не смог найти хороших гибких решений. SVG в браузере сейчас выглядит всеми забытым пожилым человеком, пора его причесать, встряхнуть от пыли и отправить в спорт зал. Надеюсь описанный в этой статье метод для кого нибудь будет полезным.

    Сразу скажу да, я использовал иконочные шрифты, вот в чем здесь проблемы:
    1. Такие иконки в браузере рендерятся как шрифт и в Windows, например, часто получаются мыльные края. Есть CSS свойства , которые должны решать эту проблему, но они работают только в WebKit и только под MAC - то есть бесполезны. Дизайнер ругался.
    2. Только в 23 Chrome и только под Windows такой шрифт начал исчезать, а в некоторых случаях сильно «рвать» остальную верстку сайта. Я много раз пользовался такими шрифтами, но первый раз со своими собственными иконками. И первый раз такая проблема.
    3. Невозможно добавлять внутреннюю тень. В проекте это было обязательно. Дизайнер ругался.
    4. Вес такого шрифта. C SVG не сравнится.
    5. Все-таки SVG имеет больше возможностей по сравнению со шрифтом.

    Приступим или исходные данные. Исходные данные - чиcтый HTML документ с подключенным к нему main.css или то место, где мы будем писать стили наших иконок.
    Так же добавим SVG документ в тег body. В нем, в разделе defs, мы будем декларировать формы наших иконок в виде clip-path и фильтры для них (внутренняя тень).
    Как декларировать SVG лучше подсмотреть у вредного старичка , так как он самый превередливый.

    Добавляем форму иконки Как получить SVG код, я думаю, писать не нужно? Достаточно просто открыть SVG файл в текстовом редакторе или воспользоваться любым векторным редактором, например Illustrator. Для наглядности здесь я показываю только SVG код из нашего HTML документа (помните, что он находится в теге body). Создаем тег clipPath и добавляем в него SVG форму иконки.

    Мы создали путь для иконки в виде сердца. Прошу обратить внимание на аттрибут id="heart-path" у тега clipPath.
    Через него мы будем ссылаться на форму нашей иконки.

    Добавляем иконки Вставляем в HTML документ нашу иконку. Она состоит из маленького SVG документа, внутрь которого вставлен квадрат:


    Сразу видим небольшой недостаток подхода - иконка состоит из двух элементов. Проблема, на мой взгляд, терпимая так как структура у всех иконок абсолютно одинаковая. Если что, можно легко найти/заменить/убрать через поиск по всему проекту.

    Обратите внимание на цифру 512. Это размер квадрата в который была вписанна иконка, когда рисовалась в редакторе. С Вашей иконкой может быть иначе. Класс heart-icon для задания формы иконки в CSS, класс icon - объединяющий класс для всех иконок (их же будет масса?).

    Последний шаг. Добавляем CSS Давайте посмотрим что получилось. Если Вы все сделали правильно, то увидите черный квадрат 512 на 512 пикселя. Малевич уже одобряет. Но, боюсь, наш с вами манифест супрематизма никто уже не оценит. Продолжаем.

    Все правильно, иконок нет? Приступаем к самому интересному - CSS.

    В main.css который мы подключили к документу пишем стили для классов heart-icon и icon.

    Icon{ width:32px; height:32px; cursor:pointer; fill: #ccc; } Наш черный квадрат становится серым и 32х32 пикселя. Свойство fill задает заливку нашей иконки.

    Heart-icon rect{ clip-path:url("#heart-path"); } Наконец-то появляется форма иконки! clip-path именно то cвойcтво, которое заставляет браузер брать форму по #heart-path и применять ее к квадрату.

    Добавим поведение для иконки. Это будут:hover, :active состояния и checked класс.

    Heart-icon rect{ clip-path:url("#heart-path"); } .icon:hover{ fill: #999; } .icon:active, .icon.checked{ fill:red; }

    Добавляем внутренюю тень Для этого мы будем использовать SVG filter.
    Сразу предупреждаю. Для данного примера у меня возникали небольшие трудности с иконками при использовании фильтра поверх них. Часть из них иногда исчезала. Иногда. Может только у меня. Будьте на чеку. И еще одна проблема - чтобы фильтр накладывался красиво нужно добавить еще один элемент в иконку. Да, очень жаль. Теперь иконка с фильтром = 3 элемента. Так что если Вам нужно воплатить трендовый флет дизайн , смело .

    Добавим элемент:
    Тэг и есть тот самый элемент, который используется для фильтра.

    Добавляем в раздел SVG документа фильтр:

    Описывать как работает фильтр, я не стану. Вы запросто прочитаете это в интернете. Это ведь тема для отдельного поста. Просто покрою его комментариями.
    Обратите внимание что у фильтра тоже есть id="inset-shadow"

    Добавляем к иконкам тень
    .icon g{ filter:url("#inset-shadow") }
    Вот и все . Хочется мне написать. Но это было бы неправдой.

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

    Но почему же не находит?! Дело в том, что здесь сталкиваются 2 браузерных мира. Наш путь url("#heart-path") Opera воспринимает как путь относительный файла CSS или url("main.css#heart-path") вместо url("index.html#heart-path"), как делают это остальные. Если задать путь эксклюзивно как url("index.html#heart-path"), то браузеры не парсят SVG документ внутри index.html, так как считают его внешним источником. Такие же проблемы возникают и у Mozilla, как только Вы переносите main.css за пределы каталога с файлом index.html. IE же в этом вопросе солидарен с WebKit. А WebKit в свою очередь не очень дружит с внешними источниками. Им нужен внутренний.

    Разводим миры по углам. В смысле, мирим. То есть, заставляем водить хоровод.
    Да, речь пойдет о кроссбраузерности.

    Итак нам нужно:

  • Два CSS файла с разными путями для двух разных миров.
  • Редактировать и поддерживать стили иконок в одном месте(файле).
  • Иметь один источник декларации форм иконок и фильтров - один SVG документ.
  • Не задумываться об этом в дальнейшем при разработке.
  • Приступим. В решении этих задач нам помогут препроцессоры. В качестве CSS препроцессора в данном примере я буду использовать Stylus , который незаслуженно обделен вниманием русскоязычного сообщества разработчиков, но максимально просто и наглядно проиллюстрирует данный пример.
    В качестве HTML препроцессора я буду использовать PHP, самый массовый препроцессор и серверный язык одновременно. Любой разработчик, пользовавшийся когда-нибудь препроцессором запросто напишет этот пример для своего любимого инструмента. Главное принцип.

    Давайте переименуем файл index.html в index.php. После этого создадим папку /css и разместим в ней файл icons.svg, куда перенесем наш большой SVG документ с декларациями форм иконок.

    На месте большого SVG документа в index.php напишем PHP выражение

    которое включает текст файла icons.svg на то место, где встречается само выражение.
    Пункт 3 выполнен, можно вычеркивать.

    Теперь пункт 1 и 2.

    В каталоге /css создадим файл icons.styl. Это будет именно то одно место, где мы будем редактировать стили наших иконок. Переместим в него все содержимое файла main.css и оформим в виде миксина icons_mixin:
    icons_mixin(path = "") .heart-icon rect{ clip-path:url(path + "#heart-path"); } .play-icon rect{ clip-path:url(path + "#play-path"); } .icon{ width:32px; height:32px; cursor:pointer; fill: #ccc; g{ filter:url(path + "#inset-shadow") } &:hover{ fill: #999; } &:active, &.checked{ fill:red; } }
    Миксин принимает в качестве параметра путь к SVG формам. Его мы будем использовать при формировании путей для разных браузеров.
    CSS стили иконок нисколько не изменились, я просто добавил нестинг для удобства и наглядности примера.

    Теперь создадим еще 2 .styl файла. webkit_ie.styl и ff_op.styl.
    Первый будем использовать на нашем вебсайте по умолчанию, второй только для Mozilla и Opera.

    В файл webkit_ie.styl добавим:
    @import "icons.styl" icons_mixin()
    Импортируем файл с миксином иконок и выполняем его без параметров.
    В файл ff_op.styl добавим:
    @import "icons.styl" icons_mixin("icons.svg")
    Импортируем файл с миксином иконок и передаем ему путь к icons.svg.

    Пункт 1 и 2 выполнены. Вычеркиваем.

    Если запутались, вот так выглядит проект:

    В index.php поправим путь к стилям иконок, теперь это

    И в самом конце, перед закрывающимся тегом добавим скрипт для условного добавления стилей иконок для браузеров с движком отличным от WebKit или Trident(IE):

    var firefox = navigator.userAgent.indexOf("Firefox") != -1 ; var opera = navigator.userAgent.indexOf("Opera") != -1 ; if (firefox || opera) { document.write(""); }
    Вот и все. исходники

    Что же мы наделали!? Давайте оглянемся назад и посмотрим, что натворили. Несмотря на то, что с первого взгляда, система может показаться слишком комплексной, мне кажется, она получилась достаточно гибкая и простая (с моего второго взгляда) чтобы иметь право на жизнь.
    • Она полностью управляется с помощью CSS.
    • Она может работать в
      • IE 9-10
      • Mozilla 4+
      • Opera 11.6+
      • Safari 5.1+
      • Chrome 14+ (я думаяю и 4+, но проверял только до этой версии)
    • Она достаточно легка по весу. (Вспомним иконку плей Вес ее составляет всего 85 байт)
    • Все иконки лежат в одном файле, так что мы не будем сервер доставать запросами.
    Все задачи выполнены. Здесь с Вашего позволения я и остановлюсь. Всем большое спасибо за внимание и время, надеюсь, Вы провели его с пользой.

    Теги: Добавить метки

    На сегодняшний день существует уже не один способ создавать SVG анимацию. Это можно сделать с помощью тега, который вставляется прямо в код SVG . Есть специальные библиотеки, такие как Snap.svg или SVG.js .

    Мы рассмотрим немного другой подход: с помощью встроенного SVG (SVG кода прямо в HTML) и анимации отдельных частей прямо через CSS .

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

    В моих последних проектах SVG использовались редко, поэтому, думаю, эта статья представляет собой прекрасную возможность уделить ему больше внимания.

    Окончательный вид анимации очень простой. Вот как она выглядит:

    Посмотреть на CodePen

    Давайте рассмотрим, как это делается.

    1. Составляем список элементов, которые мы будем использовать

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

    Мой план заключался в том, чтобы сделать супер простую рекламу Wufoo , использовав их классический логотип, цвета и корпоративный стиль. А затем добавить немного креатива:

  • Создать эффект, будто буквы убегают со страницы. Wufoo — это веселое слово, пусть буквы тоже будут веселыми;
  • За день до этого мы разработали дизайн футболки, на лицевой стороне которой был изображен динозавр, а на задней надпись: «Быстрый. Умный. Грозный ». Это черты, которые присущи и динозаврам, и Wufoo . Не говоря уже о том, что мы обыграли слово «FORMidble » (грозный). Поэтому я захотел сделать так, чтобы в анимационном блоке появлялись и исчезали эти слова;
  • Чтобы связать эти слова с динозавром, у нас будет появляться голова T-Рекса, а затем быстро исчезать. При этом будет выводиться слово «Быстрый », что будет еще одним интересным связующим звеном для элементов.
  • Все эти элементы я загрузил в Illustrator :
  • Обратите внимание, как очерчены тексты логотипа и слогана. Это означает, что они являются просто векторными фигурами, и к ним легко можно применять эффекты, как в SVG , так и в

    Текст, который вы видите, «Быстрый. » так и остается в Illustrator в формате текста.

    Когда я сохраню файл в Illustrator , надпись останется элементом.

    2. Сохраняем в формате SVG

    Illustrator поддерживает функцию сохранения в формате SVG :


    Вы можете открыть этот SVG -файл в редакторе кода и увидеть в нем код SVG :


    3. Вычищаем SVG, задаем классы для фигур

    Вы можете пропустить код через SVGO , чтобы оптимизировать его и убрать ненужные элементы типа DOCTYPE и тому подобное.

    Но нам сейчас более важно задать различные имена классов для фигур, таким образом, мы сможем выбрать их в CSS и производить разные действия!

    4. Вставляем SVG

    Вы можете скопировать этот SVG -код и вставить его прямо в HTML, в то место, где вы хотите выводить блок. Но это всего лишь примитивный шаблон.

    Вы можете сделать что-то вроде этого:

    ...

    5. Анимация!

    Теперь все эти фигуры загнаны в DOM , и мы можем позиционировать их и задавать стили, как и для любого другого элемента HTML. Давайте сделаем это.

    Предположим, мы хотим использовать 10-секундную временную шкалу:

    Сначала выпадают и исчезают слова

    Первое, что мы хотим сделать, это вывести поочередно слова «Быстрый. Умный. Грозный. » Каждое слово будет показываться в течение одной секунды.

    Так мы создаем анимацию, в которой показ каждого слова занимает 10% времени:

    @keyframes hideshow { 0% { opacity: 1; } 10% { opacity: 1; } 15% { opacity: 0; } 100% { opacity: 0; } }

    Затем указываем первое слово и длительность всей анимации в 10 секунд (10% из которых составляет 1 секунда):

    Text-1 { animation: hideshow 10s ease infinite; }

    Следующие два слова сначала будут скрытыми (opacity: 0; ), а затем используем ту же анимацию, только с задержкой во времени, чтобы следующие слова выводились немного позже:

    Text-2 { opacity: 0; animation: hideshow 10s 1.5s ease infinite; } .text-3 { opacity: 0; animation: hideshow 10s 3s ease infinite; }

    Дополнительные 0,5 секунды нужны для того, чтобы задать интервал между выводом каждого следующего слова.

    Прыгающие буквы

    Как только мы задали анимацию для этого элемента, приступаем к эффектам для букв в слове Wufoo , которые должны прыгать в сторону вот так:

    Хитрость тут в том, что мы создаем анимационный эффект, который длится всего 5 секунд, но запускаем его один раз вперед, а затем в обратном направлении.

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

    Эффекты для каждой буквы имеют небольшую задержку во времени, поэтому они перемещаются не все одновременно, а одна за другой:

    Wufoo-letter { animation: kaboom 5s ease alternate infinite; &:nth-child(2) { animation-delay: 0.1s; } &:nth-child(3) { animation-delay: 0.2s; } &:nth-child(4) { animation-delay: 0.3s; } &:nth-child(5) { animation-delay: 0.4s; } } @keyframes kaboom { 90% { transform: scale(1.0); } 100% { transform: scale(1.1); } }

    Приведенный выше SCSS -код — это просто короткая версия, он не включает в себя префиксов (которые понадобятся вам на практике).

    Я думаю, что animation-delay это свойство, которое было бы полезно взять из оригинального CSS . Это выглядело бы более аккуратно, когда буквы сдвигаются с небольшой задержкой.

    И наконец, динозавр

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

    Поскольку для позиционирования анимации эффективнее использовать преобразования, мы сделаем это с помощью keyframes :

    @keyframes popup { 0% { transform: translateY(150px); } 34% { transform: translateY(20px); } 37% { transform: translateY(150px); } 100% { transform: translateY(150px); } }

    Мы хотим, чтобы этот фрагмент анимации выводился в «последние » приблизительно 3 секунды. Этот цикл на самом деле работает все 10 секунд, но собственно видимые эффекты вы будете наблюдать в течение последних 3 секунд.

    Когда translateY (150 пикселей) применен в эффекте, динозавр перемещается так далеко вниз вне поля блока, что вы его не видите.

    Но в течение 37% времени этой анимации (около 3 секунд) вы видите, что он медленно двигается вверх, а затем быстро убирается вниз.

    Когда мы применим эту анимацию, мы убедимся что:

    • Динозавр сначала скрыт;
    • Вывод этого фрагмента анимации задерживается во времени, так что он начинается сразу после того, как буквы в слове логотипа закончили свой пляс (совершили смешение в сторону и вернулись на место).

    Trex { transform: translateY(150px); animation: popup 10s 6.5s ease infinite; }

    Динозавр падает вниз как раз в последнюю секунду так, чтобы сразу после этого в блоке снова появилось слово «Быстрый » (интервал воспроизведения анимации установлен на infinite , чтобы она запускалась по кругу снова и снова). Это привносит немного веселой синергии.

    6. Делаем блок кликабельным / интерактивным объявлением

    Одной из полезных особенностей SVG является возможность масштабировать объекты до любого размера без потери качества.

    Чтобы создать встроенный блок SVG с сохранением оригинального качества изображений, мы можем использовать технику ol’ padded box .

    ... .wufoo-ad-wrap { height: 0; padding-top: 100%; position: relative; } .wufoo-ad { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

    Идея заключается в том, что «обертка » всегда будет принимать форму квадрата, отталкиваясь от значения его ширины. Затем мы задаем абсолютные значения позиции SVG внутри этого идеального квадрата, размеры которого подгоняются, исходя из ширины.

    Поскольку это объявление (которое, конечно, должно быть кликабельным), то в качестве содержащего контейнера вместо , вы можете использовать , просто убедитесь, что вы установите его в качестве display: block; .

    Перед тем как начать разговор о SVG анимации, давайте разберемся, что такое SVG.
    S calable V ector G raphics - масштабируемая разметка в екторной графики. Предназначена для описания двумерной векторной и смешанной векторно/растровой графики в формате XML. Позволяет задать любую фигуру компактной строкой, описывающей путь от начальной точки до конечной через любые промежуточные координаты.

    Формат SVG имеет ряд достоинств:

      SVG - векторный формат, а это позволяет масштабировать изображение без потери качества.

      Текст в графике SVG не является изображением, поэтому его можно выделять и копировать, он индексируется поисковыми машинами.

      SVG - открытый стандарт, то есть пользователь может изменить рисунок, поменяв содержание файла SVG.

      Совместимость с таблицами стилей (CSS), которые используются для описания внешнего вида страниц сайтов.

      Анимация реализована в SVG с помощью языка SMIL. Элементами можно управлять при помощи JavaScript.

    И несколько недостатков, куда же без них:

    • Сложность использования в крупных картографических приложениях. Мелкие детали описывать слишком трудоёмко.

    • Чем больше в изображении мелких деталей, тем быстрее растёт размер SVG-данных.

    Пример SVG кода:

    Исполнение данного кода:

    В даном изображении можно просто изменить параметры в коде. Для примера - картинка с изображением занимает 35.5 КБ, а код SVG - 426 байт.

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

    Так зачем же разработчику использовать SMIL? Есть некоторые свойства SVG, которые невозможно изменить и анимировать при помощи CSS. Например, атрибут d=””, в котором находится набор данных, определяющих форму элемента. Недостающие возможности анимации на CSS можно восполнить с помощью JavaScript. Для этого есть ряд библиотек. Это будет целесообразно, если браузер (например Opera Mini) не поддерживает SMIL анимацию.

    Целевой объект анимации задается с помощью xlink:href.

    Если атрибут xlink:href не задан, то целевым элементом становится родительский элемент:

    Атрибут attributeName используется для указания имени атрибута, который будет анимироваться. К примеру, если нужно анимировать положение центра фигуры на оси Y, нужно задать “сy” в качестве значения атрибута attributeName.

    Вот код, который позволяет анимировать движение по оси Y синего круга из предыдущего примера:

    В течение 5 секунд (dur="5s"), после клика на синий круг (begin="click"), он будет двигаться по оси Y, начиная с точки from="300" в точку to="100". После выполнения - анимация остановится в конечной точке (fill="freeze"). Чтобы задать бесконечное повторение анимации, достаточно добавить атрибут repeatCount="indefinite".

    Также, можно задать начало выполнения анимации после загрузки страницы. Или же подключить функцию по истечению некоторого времени после загрузки, добавить анимацию элемента страницы с задержкой после клика и тому подобное.

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