Wie ändere ich die Farbe eines SVG-Bildes mit CSS (jQuery SVG Image Replacement)?


437

Dies ist eine Selbst-Q & A eines praktischen Codes, 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.

Hier ist also, was ich mir ausgedacht habe, was meiner Meinung nach der mit Abstand einfachste Weg ist, SVG-Dateien auf einer Website zu verwenden. Es basiert auf den frühen Methoden zum Ersetzen von Text zu Bild, wurde jedoch meines Wissens noch nie für SVGs durchgeführt.

Das ist die Frage:

Wie kann ich ein SVG einbetten und seine Farbe in CSS ändern, ohne ein JS-SVG-Framework zu verwenden?


1
Leider funktioniert das img-Tag nicht mit SVG-Dateien im IE. Denken Sie also daran. IE erkennt eingebettete Tags. Wie auch immer, gute Arbeit!

2
Für svg sollten Sie die CSS-Eigenschaft "fill" verwenden. Für Bilder ist es angebracht, "Filter" zu verwenden. "Filter" funktioniert zwar für beide, aber es ist nicht erforderlich, all diese Arbeiten für eine Vektorgrafik auszuführen.
Samy Bencherif

Antworten:


536

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

<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>

Dies ist genau so, wie Sie ein normales Bild einbetten würden. Beachten Sie, dass Sie den IMG so einstellen müssen, dass er eine Klasse von svg hat. Die 'Social-Link'-Klasse dient nur als Beispiel. 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 Klasse 'svg' und ersetzt sie durch die Inline-SVG aus der verknüpften Datei. Der große Vorteil besteht darin, dass Sie CSS verwenden können, um die Farbe des SVG jetzt wie folgt zu ändern:

svg:hover path {
    fill: red;
}

Der von mir geschriebene jQuery-Code portiert auch die ID und Klassen der Originalbilder. Also funktioniert dieses CSS auch:

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

Oder:

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

Ein Beispiel dafür finden Sie hier: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

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


6
Es kann manchmal in Safari nicht funktionieren (zum Beispiel), um sicherzustellen, dass zurückgegebene Daten lesbar sind, ersetzen Sie das });von $ .get durch}, 'xml');
Joan

29
Sie könnten wahrscheinlich sogar den Selektor durch ersetzen img[src$=".svg"]und die Notwendigkeit für die svgKlasse beseitigen .
Casey Chu

2
@LeonGaban Ich glaube nicht, dass es eine Möglichkeit gibt, die Füllung eines Hintergrundbilds anzuvisieren. Es wäre super hilfreich, wenn Sie könnten!
Drew Baker

3
Ein bisschen spät, @LeonGaban, aber ein besserer Weg, dies zu tun, wäre wahrscheinlich, das Füllattribut vollständig zu entfernen und sich auf eine CSS-Datei zu verlassen, um dem übergeordneten SVG eine Füllung hinzuzufügen. $('#ico_company path').removeAttr('fill'). Dann könnten Sie #ico_company { fill: #ccc }in Ihrer CSS-Datei
Bioball

2
@Soaku Es wäre einfach, wenn jQuery alle Pfade so einstellen würde, dass sie mit der Schriftfarbe identisch sind, und dabei etwa var var = $ img.closest ('p'). Css ('color'); $ svg.find ('path'). attr ('fill', color); `Aber ich denke, das ist ein Job, der besser CSS überlassen bleibt.
Drew Baker

56

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

1
Wenn Sie kein width attr haben, wird nur eines mit einer falschen Nummer erstellt. width="170.667"in meinem Fall
StallingOne

2
Dies ist nicht perfekt, da es die vorherigen IMG-Dimensionen verliert.
RichieHH

Hallo, nehme an, ich habe unterschiedliche SVGs mit jeweils unterschiedlichen Farben. Mit dieser Methode werden alle meine SVG-Farben mit denen des ersten SVG identisch, das in einer Schleife ausgeführt wird. Irgendeine Idee, wie ich das umgehen kann, damit jede Farbe dieselbe bleibt wie zuvor?
tnkh

1
Beachten Sie, dass Sie, wenn Ihr SVG auch aus Nicht- pathFormen (wie rect) besteht, diese auch in CSS verarbeiten müssen
Mugen

33

Sie können die CSS- filterEigenschaft jetzt in den meisten modernen Browsern verwenden (einschließlich Edge, jedoch nicht IE11). Es funktioniert sowohl mit SVG-Bildern als auch mit anderen Elementen. Sie können Farben verwenden hue-rotateoder invertändern, obwohl Sie damit nicht unabhängig voneinander verschiedene Farben ändern können. Ich verwende die folgende CSS-Klasse, um eine "deaktivierte" Version eines Symbols anzuzeigen (wobei das Original ein SVG-Bild mit gesättigten Farben ist):

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

Dies macht es in den meisten Browsern hellgrau. Im IE (und wahrscheinlich in Opera Mini, das ich nicht getestet habe) wird es durch die Opazitätseigenschaft merklich ausgeblendet, die immer noch ziemlich gut aussieht, obwohl sie nicht grau ist.

Hier ist ein Beispiel mit vier verschiedenen CSS-Klassen für das Twemoji- Glockensymbol: Original (gelb), die oben genannte "deaktivierte" Klasse hue-rotate(grün) und invert(blau).


Ich habe gerade bemerkt, dass invertieren eine gute Lösung ist, wenn Sie keine Symbolschriftarten erstellen möchten. Ich habe diesen jQuery-Code verwendet, um das Symbol im Header meiner Website entsprechend der CSS-Farbeigenschaft zu ändern (beachten Sie, dass ich weiße PNG-Symbole verwende):if ($('.w3-top img').css("color") == "rgb(0, 0, 0)") { $('.w3-top img').css("filter", "invert(100%)"); $('.w3-top img').css("-webkit-filter", "invert(100%)"); };
RedClover

Toller Ansatz. Ich habe meine SVG-XML bearbeitet, um die Farbe des Zielsymbols hinzuzufügen, und dann eine .icon-deaktivierte Klasse verwendet, um sie auszublenden.
SushiGuy

Beachten Sie, dass alte Explores Filter nicht unterstützen: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe

25

Alternativ können Sie CSS verwenden mask. Die gewährte Browserunterstützung ist nicht gut, Sie können jedoch einen Fallback verwenden

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}

14
MDN gibt an, dass -webkit-maskes auf keiner Produktionswebsite verwendet werden darf.
Vaindil

1
färbt das svg nicht
vishal

Vielleicht ist es wichtig zu sagen, dass diese Lösung jetzt, vier Jahre später, in allen gängigen Browsern funktioniert. Gerade hier getestet und es ist 100% ok.
Daniel Lemes

23

Wenn Sie Dateien (PHP-Include oder Include über das CMS Ihrer Wahl) in Ihre Seite aufnehmen können, können Sie den SVG-Code hinzufügen und in Ihre Seite aufnehmen. Dies funktioniert genauso wie das Einfügen der SVG-Quelle in die Seite, macht jedoch das Seitenmarkup sauberer.

Der Vorteil ist, dass Sie Teile Ihrer SVG über CSS auf Hover ausrichten können - kein Javascript erforderlich.

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

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

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

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


3
Für diejenigen, die AngularJS verwenden:<div ng-include="'svg.svg'"></div>
Mikel

Keine sehr elegante Lösung zum Speichern von SVG-Daten in einer Datenbank. Nicht falsch, aber das Auspumpen von xml / html / svg-DOM-Daten aus einer API oder einem CMS, anstatt Vorlagen oder andere Assets zu verwenden, fühlt sich einfach falsch an.
ChristoKiwi

Vielen Dank für diesen Beitrag ... Die fortschrittlichsten Websites verschachteln heute SVG-Daten, um alle Arten von Aktivitäten zu ermöglichen. Ohne diese Antwort hätte ich das nicht erraten!
WebMan

Wenn Ihre SVG über transparente Bereiche verfügt, gelten diese nicht als schwebend und es kann zu einem "auffälligen Schwebeflug" kommen. Um dies zu beheben, fügen Sie einfach ein Wrapper-Element hinzu (ein <a>, falls dies zweckmäßig ist) und fügen Sie es dann der CSS-Regel hinzu. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }Oder eliminieren Sie einfach den ursprünglichen Schwebeflug des SVG-Pfads, da Sie ihn jetzt ohnehin über das Wrapper-Element anvisieren.
Neil Monroe

18

@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. Aus diesem Grund hielt ich es für eine gute Idee, für AngularJS-Benutzer einen Code einzufügen, der der Lösung von @Drew Baker folgt.

AngularJs Weg des gleichen Codes

1. HTML : Verwenden Sie das folgende Tag in Ihrer HTML-Datei:

<svg-image src="/icons/my.svg" class="any-class-you-wish"></svg-image>

2. Direktive : Dies ist die Direktive, die Sie benötigen, um das Tag 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('<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]);
  });
});

1
Ihre Lösung funktioniert nicht, könnte sein<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent

@guillaumevincent, wenn Sie es mit verwenden möchten, ng-includedann ändern Sie einfach diese Zeile var imgURL = element.attr('src');invar imgURL = element.attr('ng-include');
Max

Dies ist eine sehr praktische Lösung, aber seien Sie vorsichtig, wenn Sie sie übermäßig verwenden, da dies die Leistung erheblich beeinträchtigen kann - dh ein Satz von 5 Freigabesymbolen, die in einer Artikelliste oder ähnlichem wiederholt werden.
Skxc

1
Es gibt ein Problem mit Ihrem Code im IE. Sie können nur if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }anstelle von split und for loop verwenden.
Robert Bokori

2
Tolle Arbeit! Für ein bestimmtes Image müssen Sie jedoch das erste Element von svg ( angular.element(data)[0];) abrufen und es mit dem IE verwenden if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. Möglicherweise möchten Sie cache: trueauch die Optionen hinzufügen , da $http.getsonst Ihre Seite möglicherweise sehr langsam wird.
Leo

16

Mir ist klar, dass Sie dies mit CSS erreichen möchten, aber nur zur Erinnerung, falls es sich um ein kleines, einfaches Bild handelt - Sie können es jederzeit in Notepad ++ öffnen und den Pfad / die Füllung des beliebigen Elements ändern:

<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"/>

Es könnte eine Menge hässlicher Schriften retten. Es tut uns leid, wenn es nicht auf der Basis ist, aber manchmal können die einfachen Lösungen übersehen werden.

... selbst das Austauschen mehrerer SVG-Bilder ist möglicherweise kleiner als einige der Codefragmente für diese Frage.


7

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

Es ersetzt das SVG-Element nach dem Rendern und platziert es in einem divElement, sodass das CSS leicht geändert werden kann. Dies hilft bei der Verwendung derselben SVG-Datei an verschiedenen Orten mit unterschiedlichen Größen / Farben.

Die Verwendung ist einfach:

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

Danach können Sie leicht haben:

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

Hallo, danke für die Bereitstellung dieser Lösung. Ich habe es versucht und es ergibt: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[Objekt SVGSVGElement]] </ div> Im HTML wird dann nur [[Objekt SVGSVGElement]] eingefügt. Weißt du was das Problem ist? Eine andere Frage: Hat dies einen großen Einfluss auf die Leistung oder kann ich es für viele SVGs auf einer Seite verwenden? Und schließlich ist es noch auf Winkel 1.3 (die Laube).
Bersling

Welche Winkelversion verwenden Sie? Sie sind auf Ihr Problem nicht gestoßen. Vielleicht liegt es an der SVG? In Bezug auf die Leistung ist der Schalter relativ schwer, ich habe ihn selbst für 10 verwendet und er war in Ordnung. Ich denke, das hängt von der Menge / Größe ab. Probieren Sie ihn aus und experimentieren Sie damit. Was ist das Problem mit der Laube? Verwenden Sie eine andere Version und es liegt ein Konflikt vor?
Omri Aharon

5

TL / DR: GO here-> https://codepen.io/sosuke/pen/Pjoqqp

Erläuterung:

Ich gehe davon aus, dass Sie HTML wie folgt haben:

<img src="/img/source.svg" class="myClass">

Gehen Sie auf jeden Fall die Filterroute, dh. Ihr SVG ist höchstwahrscheinlich schwarz oder weiß. Sie können einen Filter anwenden, um die gewünschte Farbe zu erhalten. Ich habe beispielsweise ein schwarzes SVG, das mintgrün sein soll. Ich invertiere es zuerst in Weiß (was technisch gesehen alle RGB-Farben sind) und spiele dann mit der Farbsättigung usw. Um es richtig zu machen:

filter: invert(86%) sepia(21%) saturate(761%) hue-rotate(92deg) brightness(99%) contrast(107%);

Noch besser ist, dass Sie einfach ein Tool verwenden können, um das gewünschte Hex in einen Filter für Sie zu konvertieren: https://codepen.io/sosuke/pen/Pjoqqp


Dies ist eine großartige Lösung nur für CSS, und der Codepen von Hex zu Filter ist einfach fantastisch.
Richi González

4

Hier ist eine Version knockout.jsbasierend auf der akzeptierten Antwort:

Wichtig: Für das Ersetzen ist tatsächlich auch jQuery erforderlich, aber ich dachte, es könnte für einige nützlich sein.

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 bewerben data-bind="svgConvert: true"Sie sich einfach auf Ihr img-Tag.

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


2
Das ist toll! Wenn Sie es auf die nächste Stufe bringen möchten, haben wir eine aktualisierte Version, die Caching enthält, sodass dieselbe SVG nicht zweimal angefordert wird. github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker

Ich war etwas besorgt darüber, hatte aber keine Zeit, mich selbst darum zu kümmern.
Ich

1
@DrewBaker Eigentlich war ich mehr besorgt, dass das img-Tag die Datei anfordern und dann das geterneut anfordern würde. Ich überlegte, das Attribut auf dem Tag srcin ein data-srcAttribut zu ändern img, kam jedoch zu dem Schluss, dass moderne Browser wahrscheinlich klug genug sind, um die Datei trotzdem zwischenzuspeichern
Simon_Weaver,

3

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

3

Es gibt eine Open-Source-Bibliothek namens SVGInject, die das onloadAttribut verwendet, um die Injektion auszulösen. Sie finden das GitHub-Projekt unter https://github.com/iconfu/svg-inject

Hier ist ein minimales Beispiel für die Verwendung von SVGInject:

<html>
  <head>
    <script src="svg-inject.min.js"></script>
  </head>
  <body>
    <img src="image.svg" onload="SVGInject(this)" />
  </body>
</html>

Nach dem Laden des Bildes onload="SVGInject(this)löst das die Injektion aus und das <img>Element wird durch den Inhalt der im srcAttribut bereitgestellten SVG-Datei ersetzt .

Es löst mehrere Probleme mit der SVG-Injektion:

  1. SVGs können ausgeblendet werden, bis die Injektion beendet ist. Dies ist wichtig, wenn bereits während der Ladezeit ein Stil angewendet wird, der andernfalls einen kurzen "nicht gestylten Inhaltsblitz" verursachen würde.

  2. Die <img>Elemente injizieren sich automatisch. Wenn Sie SVGs dynamisch hinzufügen, müssen Sie sich keine Gedanken mehr über das erneute Aufrufen der Injektionsfunktion machen.

  3. Jeder ID in der SVG wird eine zufällige Zeichenfolge hinzugefügt, um zu vermeiden, dass dieselbe ID mehrmals im Dokument enthalten 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 Mitautor von SVGInject


1
Diese Lösung gefällt mir am besten, weil sie sich um dynamisch hinzugefügte SVGs kümmert.
VickyB

2

Wenn wir eine größere Anzahl solcher SVG-Bilder haben, können wir auch die Hilfe von Schriftdateien verwenden.
Auf Websites wie https://glyphter.com/ können wir eine Schriftartdatei von unseren SVGs erhalten.


Z.B

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

5
Ich persönlich hasse die Technik "Bilder als Schrift". Es macht das Hinzufügen / Bearbeiten von Bildern schwierig und fügt eine Menge unsinniger Markups hinzu. Schriftarten sollten Schriftarten sein, Bilder sollten Bilder usw. sein
Drew Baker

Einverstanden. Sie müssen sich auch die den Zeichen zugewiesenen Bilder merken / nachschlagen. Für den speziellen Fall, dass Bilder als Symbole / Schaltflächen / Aufzählungszeichen verwendet werden und eher als Text als als Medien fungieren, können Schriftdateien auch eine Alternative sein
Abhishek Borar

Selbst Github verwendet keine Schrift mehr für das Symbol github.com/blog/2112-delivering-octicons-with-svg
gagarine

2

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

Hier ist der Rollover-Effekt mit reinem CSS und SVG.

Ich weiß, dass es chaotisch ist, aber Sie können dies auf diese Weise tun.

 .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">&nbsp;</a>

Hier können Sie Ihre SVG in Daten-URL konvertieren

  1. https://codepen.io/elliz/full/ygvgay
  2. https://websemantics.uk/tools/svg-to-background-image-conversion/

Dies würde bei komplexen SVGs nicht funktionieren, bei denen nur bestimmte Pfade / Polygone / usw. beim Schweben geändert werden sollen, oder?
Drew Baker

Nein, Sie können ... aber es ist sehr komplex
Patelarpan

Es ist nur Lösungen für icon
patelarpan

Wenn einige mit Symbol arbeiten. Dann ist es großartig. Bootstrap 4 verwenden auch diese Technik
Patelarpan

2

Da SVG im Grunde genommen Code ist, benötigen 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 den Inhalt "wie er ist" in einem div-Container gedruckt

<div class="fill-class"><?php echo $content;?></div>

Um die Regel endgültig auf die SVG-Childs des Containers in CSS festzulegen

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

Ich habe diese Ergebnisse mit einem Material-Symbol SVG erhalten:

  1. Mozilla Firefox 59.0.2 (64-Bit) Linux

Geben Sie hier die Bildbeschreibung ein

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

Geben Sie hier die Bildbeschreibung ein

  1. Opera 53.0.2907.37 Linux

Geben Sie hier die Bildbeschreibung ein


1

Die ausgewählte Lösung ist in Ordnung, wenn jQuery alle SVG-Elemente in Ihrem DOM verarbeiten soll und Ihr DOM eine angemessene Größe hat. Wenn Ihr DOM jedoch groß ist und Sie sich entscheiden, Teile Ihres DOM dynamisch zu laden, ist es wirklich nicht sinnvoll, das gesamte DOM erneut zu scannen, um nur SVG-Elemente zu aktualisieren. Verwenden Sie dazu stattdessen ein jQuery-Plugin:

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

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

<svg src="images/someSvgFile.svg" height="45" width="45" class="mySVGClass"/>

Und wende das Plugin an:

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

Ja, es gibt sicherlich effizientere Möglichkeiten, den von mir angegebenen Code zu verwenden. So verwenden wir es tatsächlich auf Produktionsstätten. Es speichert SVGs zwischen! github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker

1

Für: Hover-Ereignisanimationen können wir die Stile in der SVG-Datei belassen, z

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

Überprüfen Sie dies auf svgshare

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.