Wie ändert man die Farbe des SVG-Bildes mit CSS (jQuery SVG Image Replacement)?

Dies ist ein Selbst-Q & A von einem handlichen Code, den ich mir ausgedacht habe.

Derzeit gibt es keine einfache Möglichkeit, ein SVG-Bild einzubetten und dann über CSS auf die SVG-Elemente zuzugreifen. Es gibt verschiedene Methoden zur Verwendung von JS-SVG-Frameworks, die jedoch zu kompliziert sind, wenn Sie lediglich ein einfaches Symbol mit einem Rollover-Status erstellen.

Also hier ist, was ich gefunden habe, was ich denke, ist bei weitem der einfachste Weg, SVG-Dateien auf einer Website zu verwenden. Es nimmt sein Konzept von den frühen Text-zu-Bild-Ersatzmethoden, aber soweit ich weiß, wurde es nie für SVGs gemacht.

Das ist die Frage:

Wie bette ich ein SVG ein und ändere seine Farbe in CSS, ohne ein JS-SVG-Framework zu verwenden?

Verwenden Sie zunächst ein IMG-Tag in Ihrem HTML, um eine SVG-Grafik einzubetten. Ich habe Adobe Illustrator verwendet, um die Grafik zu erstellen.

 

Das ist genau so, als würde man ein normales Bild einbetten. Beachten Sie, dass Sie den IMG auf eine class von SVG festlegen müssen. Die class “soziale Verbindung” ist nur zum Zweck des Beispiels. Die ID ist nicht erforderlich, aber nützlich.

Verwenden Sie dann diesen jQuery-Code (in einer separaten Datei oder inline im 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'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'); }); 

Der obige Code sucht nach allen IMGs mit der class ‘svg’ und ersetzt sie durch die Inline-SVG aus der verknüpften Datei. Der große Vorteil ist, dass Sie jetzt CSS verwenden können, um die Farbe des SVG jetzt zu ändern:

 svg:hover path { fill: red; } 

Der jQuery-Code, den ich geschrieben habe, portiert auch die IDs und classn der Originalbilder. Also dieses CSS funktioniert auch:

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

Oder:

 .social-link:hover path { fill: red; } 

Sie können ein Beispiel dafür hier sehen: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Wir haben eine kompliziertere Version, die Caching beinhaltet: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

Stil

 svg path { fill: #000; } 

Skript

 $(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'); }); }); 

Wenn Sie auf Ihrer Seite Dateien einfügen können (PHP enthalten oder über ein CMS Ihrer Wahl einbinden), können Sie den SVG-Code hinzufügen und ihn in Ihre Seite einfügen. Dies funktioniert genauso wie das Einfügen der SVG-Quelle in die Seite, macht das Seiten-Markup jedoch sauberer.

Der Vorteil ist, dass Sie Teile Ihrer SVG via CSS für Hover – keine Javascript erforderlich.

http://codepen.io/chriscoyier/pen/evcBu

Sie müssen nur eine CSS-Regel wie folgt verwenden:

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

Beachten Sie, dass das !important Bit erforderlich ist, um die Füllfarbe zu überschreiben.

Alternativ könnten Sie CSS- mask , gewährte Browser-Unterstützung ist nicht gut, aber Sie könnten ein Fallback verwenden

 .frame { background: blue; -webkit-mask: url(https://stackoverflow.com/questions/11978995/how-to-change-color-of-svg-image-using-css-jquery-svg-image-replacement/image.svg) center / contain no-repeat; } 

Sie können jetzt die CSS- filter in den meisten modernen Browsern (einschließlich Edge, aber nicht IE11) verwenden. Es funktioniert auf SVG-Bildern sowie anderen Elementen. Sie können hue-rotate oder invert verwenden, um colors zu ändern, obwohl Sie nicht verschiedene colors unabhängig voneinander ändern können. Ich verwende die folgende CSS-class, um eine “deaktivierte” Version eines Symbols anzuzeigen (wobei das Original ein SVG-Bild mit gesättigter Farbe ist):

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

Dies macht es in den meisten Browsern hellgrau. In IE (und wahrscheinlich Opera Mini, die ich nicht getestet habe) ist es merklich durch die Opazität Eigenschaft verblasst, die immer noch ziemlich gut aussieht, obwohl es nicht grau ist.

Hier ist ein Beispiel mit vier verschiedenen CSS-classn für das Twemoji- Glockensymbol: Original (gelb), die obige class “deaktiviert”, hue-rotate (grün) und invert (blau).

 .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>           

@Drew Baker gab eine großartige Lösung, um das Problem zu lösen. Der Code funktioniert ordnungsgemäß. Diejenigen, die AngularJs verwenden, können jedoch eine große Abhängigkeit von jQuery feststellen. Folglich dachte ich, es wäre eine gute Idee, für AngularJS-Benutzer einen Code einzufügen, der @ Drew Bakers Lösung folgt.

Angulars Weg des gleichen Codes

1. Html : Verwenden Sie den folgenden Tag in Ihrer HTML-Datei:

  

2. Richtlinie : Dies ist die Richtlinie, die Sie benötigen, um das Etikett zu erkennen:

 '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. Unit-Test mit Karma-Jasmin :

 '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 = '< ?xml version="1.0" encoding="utf-8"?>' + '' + '< !DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + '' + '' + '' + '' + '' + '' + '' + ''; $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]); }); }); 

Mir ist klar, dass du dies mit CSS erreichen willst, aber nur eine Erinnerung, falls es ein kleines, einfaches Bild ist – du kannst es immer in Notepad ++ öffnen und die Füllung des Pfades / whateverelements ändern:

  

Es könnte eine Menge hässliches Skript speichern. Es tut uns leid, wenn es außerhalb der Basis ist, aber manchmal können die einfachen Lösungen übersehen werden.

… sogar mehrere Svg-Bilder austauschen kann kleiner sein als einige der Code-Schnipsel für diese Frage.

Ich habe eine Richtlinie geschrieben, um dieses Problem mit AngularJS zu lösen. Es ist hier verfügbar – ngReusableSvg .

Er ersetzt das SVG-Element, nachdem es gerendert wurde, und fügt es in ein div Element ein, wodurch sein CSS leicht änderbar wird. Dies hilft bei der Verwendung der gleichen SVG-Datei an verschiedenen Orten mit unterschiedlichen Größen / colors.

Die Verwendung ist einfach:

   

Danach können Sie leicht haben:

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

Hier ist eine Version für knockout.js basierend auf der angenommenen Antwort:

Wichtig: Es erfordert auch jQuery für das Ersetzen, aber ich dachte, dass es für einige nützlich sein könnte.

 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'); } }; 

Dann wenden Sie einfach data-bind="svgConvert: true" an Ihr img-Tag an.

Diese Lösung ersetzt das img Tag vollständig durch ein SVG, und zusätzliche Bindungen werden nicht berücksichtigt.

Hier ist ein No-Framework-Code, nur pure 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) }) 

Wenn wir eine größere Anzahl solcher SVG-Bilder haben, können wir auch Font-Dateien verwenden.
Sites wie https://glyphter.com/ können uns eine Font-Datei von unserer Svgs bekommen.


Z.B

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

Es gibt eine Open-Source-Bibliothek namens SVGInject, die das Attribut onload zum Auslösen der Injektion verwendet. Sie finden das GitHub-Projekt unter https://github.com/iconfu/svg-inject

Hier ist ein minimales Beispiel mit SVGInject:

         

Nachdem das Bild geladen wurde, wird onload="SVGInject(this) die Injektion auslösen und das -Element wird durch den Inhalt der SVG-Datei ersetzt, die im src Attribut enthalten ist.

Es triggers mehrere Probleme mit der SVG-Injektion:

  1. SVGs können versteckt werden, bis die Injektion beendet ist. Dies ist wichtig, wenn während der Ladezeit bereits ein Style angewendet wird, der sonst einen kurzen “unstyled content flash” verursachen würde.

  2. Die Elemente injizieren sich automatisch. Wenn Sie SVGs dynamisch hinzufügen, müssen Sie sich keine Gedanken darüber machen, die Injektionsfunktion erneut aufzurufen.

  3. Eine zufällige Zeichenfolge wird zu jeder ID in der SVG hinzugefügt, um zu vermeiden, dass dieselbe ID mehrfach im Dokument vorhanden ist, wenn eine SVG mehr als einmal injiziert wird.

SVGInject ist einfaches Javascript und funktioniert mit allen Browsern, die SVG unterstützen.

Haftungsausschluss: Ich bin der Co-Autor von SVGInject

Die ausgewählte Lösung ist in Ordnung, wenn Sie möchten, dass jQuery alle SVG-Elemente in Ihrem DOM verarbeitet und Ihr DOM eine angemessene Größe hat. Aber wenn Ihr DOM groß ist und Sie sich entscheiden, Teile Ihres DOMs dynamisch zu laden, macht es wirklich keinen Sinn, das gesamte DOM erneut scannen zu müssen, nur um svg-Elemente zu aktualisieren. Verwenden Sie stattdessen ein jQuery-Plugin, um dies zu tun:

 /** * 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)); 

Geben Sie in Ihrem HTML-Code ein SVG-Element wie folgt ein:

  

Und wenden Sie das Plugin an:

 $(".mySVGClass").svgLoader(); 

Da SVG im Grunde Code ist, brauchen Sie nur Inhalte. Ich habe PHP verwendet, um Inhalte zu erhalten, aber Sie können verwenden, was Sie wollen.

 < ?php $content = file_get_contents($pathToSVG); ?> 

Dann habe ich Inhalt “wie es ist” in einem div-Container gedruckt

 
< ?php echo $content;?>

Setzen Sie die Regeln für die SVG-Childs des Containers auf CSS

 .fill-class > svg { fill: orange; } 

Ich habe diese Ergebnisse mit einem Material-Icon SVG bekommen:

  1. Mozilla Firefox 59.0.2 (64-Bit) Linux

Bildbeschreibung hier eingeben

  1. Google Chrome66.0.3359.181 (Build oficial) (64 Bit) Linux

Bildbeschreibung hier eingeben

  1. Opera 53.0.2907.37 Linux

Bildbeschreibung hier eingeben

Sie können dafür ein Daten-Image verwenden. Mit Daten-Image (Daten-URI) können Sie wie inline auf SVG zugreifen.

Hier ist Rollover-Effekt mit reinem CSS und SVG.

Ich weiß es unordentlich, aber du kannst es so machen.

  .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; } 
   

für: Hover Event Animationen können wir die Stile in Svg-Datei, wie a

       

Überprüfe dies auf svgshare

Wenn dies eine statische Änderung ist, öffnen Sie die SVG-Datei in Adobe Illustrator (oder einem anderen geeigneten SVG-Editor), ändern Sie die Farbe und speichern Sie sie.