Как изменить цвет изображения SVG с помощью CSS (jQuery SVG image replacement)?
это самостоятельный вопрос и ответ на удобный кусок кода, который я придумал.
В настоящее время нет простого способа встроить изображение SVG, а затем получить доступ к элементам SVG через CSS. Существуют различные методы использования фреймворков JS SVG, но они слишком сложны, если все, что вы делаете, - это создание простого значка с состоянием опрокидывания.
Итак, вот что я придумал, и я думаю, что это самый простой способ использовать файлы SVG на веб-сайте. Он берет свою концепцию из ранние методы замены текста на изображение, но, насколько мне известно, никогда не делались для SVGs.
вот в чем вопрос:
как встроить SVG и изменить его цвет в CSS без использования JS-SVG framework?
17 ответов:
во-первых, используйте тег IMG В вашем HTML для вставки графики SVG. Я использовал Adobe Illustrator для создания графики.
<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>это так же, как вы бы встроить нормальное изображение. Обратите внимание, что вам нужно установить IMG, чтобы иметь класс svg. Класс "социальная связь" - это только для примера. Идентификатор не требуется, но является полезным.
затем используйте этот код jQuery (в отдельном файле или встроенном в голове).
/* * 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's ID to the new SVG if(typeof imgID !== 'undefined') { $svg = $svg.attr('id', imgID); } // Add replaced image's 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; }вы можете увидеть пример его работы здесь: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html
у нас есть более сложная версия, которая включает кэширование здесь: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90
стиль
svg path { fill: #000; }скрипт
$(document).ready(function() { $('img[src$=".svg"]').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 include или include через вашу CMS по выбору) на своей странице, вы можете добавить код SVG и включить его в свою страницу. Это работает так же, как вставка источника SVG на страницу, но делает разметку страницы более чистой.
преимущество в том, что вы можете настроить таргетинг на части вашего SVG через CSS для hover-не требуется javascript.
http://codepen.io/chriscoyier/pen/evcBu
вы просто должны использовать правило CSS, как это:
#pathidorclass:hover { fill: #303 !important; }отметим, что
!importantбит необходим для переопределения цвета заливки.
в качестве альтернативы вы можете использовать CSS
mask, выдано поддержка браузеров не хорошо, но вы могли бы использовать запасной вариант.frame { background: blue; -webkit-mask: url(image.svg) center / contain no-repeat; }
теперь вы можете использовать CSS
filterсвойства на большинство современных браузеров (включая край, но не IE11). Он работает на SVG изображений, а также других элементов. Вы можете использовать hue-rotate или invert для изменения цветов, хотя они не позволяют изменять разные цвета независимо. Я использую следующий класс CSS, чтобы показать "отключенную" версию значка (где оригинал-это изображение SVG с насыщенным цветом):.disabled { opacity: 0.4; filter: grayscale(100%); -webkit-filter: grayscale(100%); }это делает его светло-серый в большинство браузеров. В IE (и, вероятно, Opera Mini, который я не тестировал) он заметно потускнел из-за свойства непрозрачности, которое все еще выглядит довольно хорошо, хотя оно и не серое.
вот пример с четырьмя различными классами CSS для представляет значок колокола: оригинал (желтый), выше "отключен" класс,
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%); }<!DOCTYPE html> <html> <head> </head> <body> <span class="twa-bell"></span> <span class="twa-bell grey-out"></span> <span class="twa-bell hue-rotate"></span> <span class="twa-bell invert"></span> </body> </html>
@Дрю Бейкер дал отличное решение для решения этой проблемы. Код работает правильно. Однако те, кто использует AngularJs, могут найти большую зависимость от jQuery. Следовательно, я подумал, что это хорошая идея, чтобы вставить для пользователей AngularJS, код после решения @Drew Baker.
AngularJs способ того же кода
1. HTML-код: используйте тег ниже в вашем html-файле:
<svg-image src="/icons/my.svg" class="any-class-you-wish"></svg-image>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)[4]; 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)); }); } }; }]);3. CSS:
.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('<svg-image src="/icons/icon-man.svg" class="svg"></svg-image>'); element = $compile(element)(scope); spyOn(scope, 'manipulateImgNode').andCallThrough(); $httpBackend.whenGET(apiUrl + 'me').respond(200, {}); data = '<?xml version="1.0" encoding="utf-8"?>' + '<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->' + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + '<!-- Obj -->' + '<!-- Obj -->' + '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' + 'width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">' + '<g>' + '<path fill="#F4A902" d=""/>' + '<path fill="#F4A902" d=""/>' + '</g>' + '</svg>'; $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[0]).toBe(classList[0]); }); });
Я понимаю, что вы хотите выполнить это с помощью CSS, но просто напоминаю, если это небольшое, простое изображение - вы всегда можете открыть его в Notepad++ и изменить путь / whateverelement fill:
<path style="fill:#010002;" d="M394.854,205.444c9.218-15.461,19.102-30.181,14.258-49.527 ... C412.843,226.163,402.511,211.451,394.854,205.444z"/>Это может спасти тонну уродливого сценария. Извините, если это вне базы, но иногда простые решения можно упустить из виду.
...даже замена нескольких изображений SVG может быть меньше по размеру, чем некоторые фрагменты кода на этот вопрос.
Я написал директиву, чтобы решить эту проблему с AngularJS. Он доступен здесь - ngReusableSvg.
он заменяет элемент SVG после его визуализации и помещает его внутрь
divэлемент, что делает его CSS легко изменяемым. Это помогает использовать один и тот же файл SVG в разных местах, используя разные размеры/цвета.использование прост:
<object oa-reusable-svg data="my_icon.svg" type="image/svg+xml" class="svg-class" height="30" // given to prevent UI glitches at switch time width="30"> </object>после этого, вы можете легко:
.svg-class svg { fill: red; // whichever color you want }
вот версия для
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's ID to the new SVG if (typeof imgID !== 'undefined') { $svg = $svg.attr('id', imgID); } // Add replaced image's 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 и любые дополнительные привязки не будут соблюдаться.
здесь нет кода фреймворка, только чистый 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')[0]; 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) })
существует библиотека с открытым исходным кодом под названием SVGInject, которая использует
onloadатрибут для запуска инъекции. Вы можете найти проект GitHub по адресуhttps://github.com/iconfu/svg-injectвот минимальный пример использования SVGInject:
<html> <head> <script src="svg-inject.min.js"></script> </head> <body> <img src="image.svg" onload="SVGInject(this)" /> </body> </html>после загрузки изображения
onload="SVGInject(this)вызовет инъекцию и<img>элемент будет заменен на содержимое файла SVG, предоставленного в .это решает несколько проблем с SVG injection:
SVGs можно спрятать до тех пор пока впрыска не будет заканчивать. Это важно, если стиль уже применяется во время загрузки, что в противном случае вызвало бы краткую "вспышку неустановленного содержимого".
The
<img>элементы впрыскивают themselved автоматически. Если вы добавляете SVGs динамически, вам не нужно беспокоиться о повторном вызове функции инъекции.случайная строка добавляется каждый идентификатор в SVG, чтобы избежать наличия одного и того же идентификатора несколько раз в документе, если SVG вводится более одного раза.
SVGInject-это простой Javascript и работает со всеми браузерами, которые поддерживают SVG.
отказ от ответственности: я являюсь соавтором SVGInject
Если у нас есть большее количество таких изображений svg, мы также можем воспользоваться помощью font-файлов.
Такие сайты, какhttps://glyphter.com/ может получить нам файл шрифта из наших svgs.
например.
@font-face { font-family: 'iconFont'; src: url('iconFont.eot'); } #target{ color: white; font-size:96px; font-family:iconFont; }
поскольку SVG-это в основном код, вам нужно только содержание. Я использовал PHP для получения контента, но вы можете использовать все, что вы хотите.
<?php $content = file_get_contents($pathToSVG); ?>затем я напечатал содержимое "как есть" внутри контейнера div
<div class="fill-class"><?php echo $content;?></div>чтобы finnaly установить правило для SVG Childs контейнера на CSS
.fill-class > svg { fill: orange; }я получил эти результаты с помощью значка материала SVG:
- Mozilla Firefox 59.0.2 (64-бит) Linux
- Google Chrome66.0.3359. 181 (Build oficial) (64 бит) Linux
- Opera 53.0.2907.37 Linux
выбранное решение отлично, если вы хотите, чтобы 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 <svg> 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 = $('<a></a>').append(svg.clone()).html(); ctx.replaceWith(newHtml); }); return this; }; }(jQuery));в html укажите элемент svg следующим образом:
<svg src="images/someSvgFile.svg" height="45" width="45" class="mySVGClass"/>и применить плагин:
$(".mySVGClass").svgLoader();
вы можете использовать data-image для этого. используя data-image (data-URI) вы можете получить доступ к SVG, как встроенный.
вот эффект опрокидывания с использованием чистого CSS и SVG.
Я знаю грязный но вы можете сделать это таким образом.
.action-btn { background-size: 20px 20px; background-position: center center; background-repeat: no-repeat; border-width: 1px; border-style: solid; border-radius: 30px; height: 40px; width: 60px; display: inline-block; } .delete { background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#FB404B' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e "); border-color:#FB404B; } .delete:hover { background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#fff' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e "); background-color: #FB404B; }<a class="action-btn delete"> </a>вы можете конвертировать svg в url-адрес данных здесь
для: hover анимации событий мы можем оставить стили внутри файла svg, как будто
<svg xmlns="http://www.w3.org/2000/svg"> <defs> <style> rect { fill:rgb(165,225,75); stroke:none; transition: 550ms ease-in-out; transform-origin:125px 125px; } rect:hover { fill:rgb(75,165,225); transform:rotate(360deg); } </style> </defs> <rect x='50' y='50' width='150' height='150'/> </svg>
Если это статическое изменение, то откройте файл SVG в Adobe Illustrator (или любом подходящем редакторе SVG) измените цвет и сохраните его.



Comments