Jak zmienić kolor obrazu SVG za pomocą CSS (wymiana obrazu jQuery SVG)?

437

To jest samo pytanie i przydatny fragment kodu, który wymyśliłem.

Obecnie nie ma łatwego sposobu na osadzenie obrazu SVG, a następnie dostęp do elementów SVG przez CSS. Istnieją różne metody korzystania z frameworków JS SVG, ale są one zbyt skomplikowane, jeśli robisz tylko prostą ikonę ze stanem najazdu.

Oto co wymyśliłem, co moim zdaniem jest zdecydowanie najłatwiejszym sposobem korzystania z plików SVG na stronie internetowej. Opiera się na wczesnych metodach zamiany tekstu na obraz, ale o ile wiem, nigdy nie zrobiono tego w przypadku plików SVG.

To jest pytanie:

Jak osadzić plik SVG i zmienić jego kolor w CSS bez korzystania z frameworka JS-SVG?

Drew Baker
źródło
1
Niestety znacznik img nie działa z plikami svg w IE, więc miej to na uwadze. IE rozpoznaje tagi osadzania. W każdym razie, dobra robota!
2
W przypadku svg należy użyć właściwości css „fill”. W przypadku obrazów należy zastosować „filtr”. „Filtr” w rzeczywistości działa dla obu, ale nie jest konieczne wykonywanie całej tej pracy w przypadku grafiki wektorowej.
Samy Bencherif

Odpowiedzi:

536

Po pierwsze, użyj tagu IMG w swoim HTML, aby osadzić grafikę SVG. Użyłem programu Adobe Illustrator do wykonania grafiki.

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

To tak, jakbyś osadził normalny obraz. Pamiętaj, że musisz ustawić IMG, aby miał klasę svg. Klasa „social-link” jest tylko dla przykładu. Identyfikator nie jest wymagany, ale jest użyteczny.

Następnie użyj tego kodu jQuery (w osobnym pliku lub wbudowanym w 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');

        });

Powyższy kod wyszukuje wszystkie IMG z klasą „svg” i zastępuje je wbudowanym SVG z połączonego pliku. Ogromną zaletą jest to, że pozwala teraz używać CSS do zmiany koloru SVG, w następujący sposób:

svg:hover path {
    fill: red;
}

Kod jQuery, który napisałem, zawiera również porty oryginalnego identyfikatora obrazów i klas. Więc ten CSS też działa:

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

Lub:

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

Przykład takiego działania można znaleźć tutaj: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Mamy bardziej skomplikowaną wersję, która obejmuje buforowanie tutaj: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

Drew Baker
źródło
6
Czasami może to nie działać w Safari (np.), Aby upewnić się, że zwrócone dane są czytelne, zastąp });$ .get za pomocą}, 'xml');
Joan
29
Prawdopodobnie możesz nawet wymienić selektor img[src$=".svg"]i wyeliminować potrzebę posiadania svgklasy.
Casey Chu,
2
@LeonGaban Nie sądzę, aby istniał sposób na wypełnienie obrazu tła. Byłoby to bardzo pomocne, gdybyś mógł!
Drew Baker,
3
Nieco później, @LeonGaban, ale lepszym sposobem na to prawdopodobnie byłoby całkowite usunięcie atrybutu fill i poleganie na pliku CSS w celu dodania wypełnienia do nadrzędnego pliku svg. $('#ico_company path').removeAttr('fill'). Następnie możesz zrobić #ico_company { fill: #ccc }w swoim pliku CSS
bioball
2
@ Soaku łatwo byłoby ustawić jQuery tak, aby wszystkie ścieżki były takie same jak kolor czcionki, wykonując coś takiego jak `var color = $ img.closest ('p'). Css ('color'); $ svg.find („ścieżka”). attr („wypełnienie”, kolor); „Ale myślę, że jest to praca, którą lepiej pozostawić CSS.
Drew Baker
56

Styl

svg path {
    fill: #000;
}

Scenariusz

$(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');
    });
});
Henrik Albrechtsson
źródło
1
Jeśli nie masz attr szerokości, po prostu tworzy ona z niewłaściwym numerem. width="170.667"w moim przypadku
przeciągnięcie Jeden
2
Nie jest to idealne, ponieważ traci poprzednie wymiary img.
RichieHH,
Witaj, załóżmy, że mam inny plik svg z innym kolorem. Korzystając z tej metody, wszystkie moje kolory svg stają się takie same jak pierwszy svg, który jest zapętlony. Masz pomysł, jak mogę manewrować wokół tego, aby każdy kolor pozostał taki sam jak wcześniej?
tnkh
1
zwróć uwagę, że jeśli twój plik svg jest wykonany również z nie- pathkształtów (takich jak rect), musisz obsługiwać je również w css
Mugen
33

Możesz teraz używać właściwości CSSfilter w większości nowoczesnych przeglądarek (w tym Edge, ale nie IE11). Działa na obrazach SVG, a także na innych elementach. Możesz używać hue-rotatelub invertmodyfikować kolory, chociaż nie pozwalają one niezależnie zmieniać różnych kolorów. Używam następującej klasy CSS, aby pokazać „wyłączoną” wersję ikony (gdzie oryginał to obraz SVG o nasyconym kolorze):

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

Dzięki temu jest jasnoszary w większości przeglądarek. W IE (i prawdopodobnie Opera Mini, której nie testowałem) jest zauważalnie wyblakły przez właściwość opacity, która wciąż wygląda całkiem dobrze, chociaż nie jest szara.

Oto przykład z czterema różnymi klasami CSS dla ikony dzwonka Twemoji : oryginalna (żółta), powyższa „wyłączona” klasa, hue-rotate(zielona) i invert(niebieska).

Alddel
źródło
Zauważyłem, że odwrócenie jest dobrym rozwiązaniem, jeśli nie chcesz tworzyć czcionek ikon. Użyłem tego kodu jQuery, aby zmienić ikonę w nagłówku mojej witryny zgodnie z właściwością koloru css (zauważ, że używam białych ikon png):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
Świetne podejście. Zmodyfikowałem mój plik XML SVG, aby dodać docelowy kolor ikony, a następnie użyłem klasy z wyłączoną opcją .icon, aby go wyszarzyć.
SushiGuy
Zauważ, że stary Explores nie obsługuje filtra: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe
25

Alternatywnie możesz użyć CSS mask, przyznana obsługa przeglądarki nie jest dobra, ale możesz użyć rezerwy

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}
seanjacob
źródło
14
MDN określa, że -webkit-masknie należy go używać w żadnej witrynie produkcyjnej.
vaindil
1
nie
koloruje
Może warto powiedzieć, że teraz, cztery lata później, to rozwiązanie działa we wszystkich głównych przeglądarkach. Właśnie przetestowałem tutaj i jest w 100% ok.
Daniel Lemes,
23

Jeśli możesz dołączyć pliki (PHP włącz lub włącz przez wybrany CMS) na swojej stronie, możesz dodać kod SVG i dołączyć go do swojej strony. Działa to tak samo, jak wklejanie źródła SVG na stronę, ale czyni znaczniki strony czystszymi.

Zaletą jest to, że możesz nałożyć cel na część swojego pliku SVG za pomocą CSS do aktywowania - nie wymaga javascript.

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

Musisz tylko użyć takiej reguły CSS:

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

Należy pamiętać, że !importantbit jest niezbędny do zastąpienia koloru wypełnienia.

trebor1979
źródło
3
Dla osób używających AngularJS:<div ng-include="'svg.svg'"></div>
Mikel
Jednak niezbyt eleganckie rozwiązanie do przechowywania danych SVG w bazie danych. Nie źle, ale wypompowywanie danych DOM xml / html / svg z API lub CMS zamiast używania szablonów lub innych zasobów jest po prostu złe.
ChristoKiwi
Dziękuję za ten wkład ... Najbardziej zaawansowane strony dziś zagnieżdżają dane svg, aby umożliwić wszelkiego rodzaju aktywność, bez tej odpowiedzi nie zgadłbym!
webMan
Dodatkowo, jeśli twoje SVG ma przezroczyste obszary, nie będą się one liczyć jako zawisanie i możesz doświadczyć „zawrotnego najechania”. Aby to naprawić, po prostu dodaj element otoki (<a>, jeśli jest to wygodne), a następnie dodaj to do reguły CSS. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }Lub nawet po prostu wyeliminuj pierwotne najechanie ścieżką SVG, ponieważ i tak celujesz w nią za pomocą elementu opakowania.
Neil Monroe
18

@Drew Baker dał świetne rozwiązanie, aby rozwiązać problem. Kod działa poprawnie. Jednak ci, którzy używają AngularJs, mogą znaleźć wiele zależności od jQuery. W związku z tym pomyślałem, że dobrym pomysłem jest wklejenie dla użytkowników AngularJS, kodu podążającego za rozwiązaniem @Drew Baker.

Sposób AngularJs tego samego kodu

1. HTML : użyj poniższego znacznika w swoim pliku HTML:

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

2. Dyrektywa : będzie to dyrektywa, w której musisz rozpoznać tag:

'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. Test jednostkowy z karma-jaśminem :

'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]);
  });
});
Max
źródło
1
twoje rozwiązanie nie działa, może być<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent
@ guillaumevincent, jeśli chcesz go używać, ng-includepo prostu zmień tę linię var imgURL = element.attr('src');navar imgURL = element.attr('ng-include');
Max
Jest to bardzo przydatne rozwiązanie, ale należy go ostrożnie nadużywać, ponieważ może to bardzo mocno obniżyć wydajność - np. Zestaw 5 ikon udostępniania powtarzanych na liście artykułów lub coś w tym rodzaju.
skxc,
1
Wystąpił problem z Twoim kodem w IE. Możesz użyć tylko if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }zamiast split i for loop.
Robert Bokori,
2
Świetna robota! Ale dla niektórych obrazów musisz pobrać pierwszy element svg ( angular.element(data)[0];) i sprawić, aby działał z wykorzystaniem IE if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. Możesz także dodać cache: trueopcje, w $http.getprzeciwnym razie Twoja strona może stać się bardzo wolna.
leo
16

Zdaję sobie sprawę, że chcesz to osiągnąć za pomocą CSS, ale tylko przypomnienie w przypadku, gdy jest to mały, prosty obraz - zawsze możesz go otworzyć w Notepad ++ i zmienić wypełnienie ścieżki / whateverelement:

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

To może zaoszczędzić mnóstwo brzydkiego scenariusza. Przepraszam, jeśli jest poza bazą, ale czasami proste rozwiązania można przeoczyć.

... nawet zamiana wielu obrazów svg może mieć mniejszy rozmiar niż niektóre fragmenty kodu dla tego pytania.

DShultz
źródło
7

Napisałem dyrektywę, aby rozwiązać ten problem z AngularJS. Jest dostępny tutaj - ngReusableSvg .

Zastępuje element SVG po jego renderowaniu i umieszcza go w divelemencie, dzięki czemu jego CSS można łatwo zmieniać. Pomaga to w użyciu tego samego pliku SVG w różnych miejscach o różnych rozmiarach / kolorach.

Użycie jest proste:

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

Następnie możesz łatwo uzyskać:

.svg-class svg {
    fill: red; // whichever color you want
}
Omri Aharon
źródło
Cześć, dziękuję za zapewnienie tego rozwiązania. Próbowałem i daje: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[obiekt SVGSVGElement]] </div> W html następnie umieszcza [[obiekt SVGSVGElement]]. Czy wiesz na czym polega problem? Kolejne pytanie, czy ma to duży wpływ na wydajność, czy mogę go używać w wielu plikach SVG na stronie? I na koniec, wciąż jest na kącie 1.3 (altana).
bersling
Której wersji kątowej używasz? Nie spotkałem się z problemem… może to coś z SVG? Pod względem wydajności przełącznik jest stosunkowo ciężki, sam go użyłem na około 10 i było w porządku .. Myślę, że to zależy od ilości / wielkości, więc wypróbuj i eksperymentuj z nim. W czym problem z altaną? Czy używasz innej wersji i występuje konflikt?
Omri Aharon,
5

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

Wyjaśnienie:

Zakładam, że masz HTML tak:

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

Zdecydowanie wybierz ścieżkę filtru, tj. Twój plik SVG jest najprawdopodobniej czarny lub biały. Możesz zastosować filtr, aby uzyskać dowolny kolor, na przykład mam czarny plik SVG, który chcę miętowo zielony. Najpierw odwracam go, aby był biały (czyli technicznie wszystkie kolory RGB są pełne), a następnie bawiłem się nasyceniem odcienia itp. Aby to zrobić poprawnie:

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

Jeszcze lepsze jest to, że możesz po prostu użyć narzędzia do konwersji heksa, który chcesz w filtr dla ciebie: https://codepen.io/sosuke/pen/Pjoqqp

AhrenFullStop
źródło
To świetne rozwiązanie tylko dla css, a kodepen od hex do filtra jest po prostu niesamowity.
Richi González
4

Oto wersja knockout.jsoparta na zaakceptowanej odpowiedzi:

Ważne: W rzeczywistości wymaga również jQuery do wymiany, ale pomyślałem, że może być użyteczny dla niektórych.

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

        }
    };

Następnie po prostu zastosuj data-bind="svgConvert: true"do tagu img.

To rozwiązanie całkowicie zastępuje imgznacznik SVG i żadne dodatkowe powiązania nie byłyby przestrzegane.

Simon_Weaver
źródło
2
To jest świetne! Jeśli chcesz przenieść go na wyższy poziom, mamy zaktualizowaną wersję, która obejmuje buforowanie, więc ten sam plik SVG nie jest wymagany dwukrotnie. github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
Trochę się tym martwiłem, ale sam nie miałem czasu, żeby się tym przyjrzeć. Potrzebowałem tylko czegoś szybkiego
Simon_Weaver
1
@DrewBaker byłam bardziej zaniepokojona tym, że znacznik img zażąda pliku, a następnie getzażąda go ponownie. Zastanawiałem się nad zmianą atrybutu na tag, ale doszedłem srcdo wniosku, że współczesne przeglądarki są prawdopodobnie wystarczająco inteligentne, aby mimo wszystko buforować plikdata-srcimg
Simon_Weaver
3

Oto brak kodu frameworka, tylko czysty 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)
        })
użytkownik3144480
źródło
3

Istnieje biblioteka open source o nazwie SVGInject, która korzysta z onload atrybutu do wyzwalania zastrzyku. Projekt GitHub można znaleźć na stronie https://github.com/iconfu/svg-inject

Oto minimalny przykład użycia SVGInject:

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

Po załadowaniu obrazu onload="SVGInject(this) uruchomi się zastrzyk, a <img>element zostanie zastąpiony zawartością pliku SVG podanego w srcatrybucie.

Rozwiązuje kilka problemów z wtryskiem SVG:

  1. Pliki SVG można ukryć do momentu zakończenia wstrzykiwania. Jest to ważne, jeśli styl jest już zastosowany podczas ładowania, co w przeciwnym razie spowodowałoby krótkie „niestylizowane flashowanie zawartości”.

  2. The <img> elementy wstrzykują themselved automatycznie. Jeśli dodajesz pliki SVG dynamicznie, nie musisz się martwić o ponowne wywołanie funkcji wstrzykiwania.

  3. Losowy ciąg jest dodawany do każdego identyfikatora w pliku SVG, aby uniknąć wielokrotnego posiadania tego samego identyfikatora w dokumencie, jeśli plik SVG zostanie wstrzyknięty więcej niż jeden raz.

SVGInject to zwykły Javascript i działa ze wszystkimi przeglądarkami obsługującymi SVG.

Oświadczenie: Jestem współautorem SVGInject

Waruyama
źródło
1
Najbardziej podoba mi się to rozwiązanie, ponieważ dba ono o dynamicznie dodawane pliki SVG.
VickyB
2

Jeśli mamy większą liczbę takich obrazów svg, możemy również skorzystać z plików czcionek.
Strony takie jak https://glyphter.com/ mogą pobrać plik czcionek z naszych plików SVG.


Na przykład

@font-face {
    font-family: 'iconFont';
    src: url('iconFont.eot');
}
#target{
    color: white;
    font-size:96px;
    font-family:iconFont;
}
Abhishek Borar
źródło
5
Osobiście nienawidzę techniki „obrazy jako czcionka”. Utrudnia to dodawanie / edytowanie obrazów, dodaje wiele bezsensownych znaczników. Czcionki powinny być czcionkami, obrazy powinny być obrazami itp.
Drew Baker
Zgoda. Musisz także zapamiętać / wyszukać obrazy przypisane do postaci. ale w konkretnym przypadku, w którym obrazy są używane jako ikony / przyciski / punktory, działają bardziej jak tekst niż media, pliki czcionek mogą być również alternatywą
Abhishek Borar
nawet github nie używa już czcionki dla ikony github.com/blog/2112-delivering-octicons-with-svg
gagarine
2

Możesz do tego użyć obrazu danych. za pomocą obrazu danych (data-URI) możesz uzyskać dostęp do SVG jak inline.

Oto efekt najazdu przy użyciu czystego CSS i SVG.

Wiem, że to bałagan, ale możesz to zrobić w ten sposób.

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

Tutaj możesz przekonwertować plik SVG na adres URL danych

  1. https://codepen.io/elliz/full/ygvgay
  2. https://websemantics.uk/tools/svg-to-background-image-conversion/
patelarpan
źródło
Nie działałoby to w przypadku skomplikowanych plików SVG, w których chcesz tylko niektóre ścieżki / wielokąty / itd. Zmieniać po najechaniu myszą, prawda?
Drew Baker,
Nie możesz ... ale to bardzo skomplikowane
patelarpan
To tylko rozwiązania dla ikony
patelarpan
Jeśli niektóre działają z ikoną. To świetnie. Bootstrap 4 również korzysta z tej techniki
patelarpan
2

Ponieważ SVG jest w zasadzie kodem, potrzebujesz tylko zawartości. Użyłem PHP, aby uzyskać zawartość, ale możesz użyć, co chcesz.

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

Następnie wydrukowałem zawartość „tak jak jest” w pojemniku div

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

Aby ostatecznie ustawić regułę dla elementów potomnych SVG kontenera w CSS

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

Mam wyniki z ikoną materiału SVG:

  1. Mozilla Firefox 59.0.2 (64-bitowy) Linux

wprowadź opis zdjęcia tutaj

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

wprowadź opis zdjęcia tutaj

  1. Opera 53.0.2907.37 Linux

wprowadź opis zdjęcia tutaj

Benzoes
źródło
1

Wybrane rozwiązanie jest w porządku, jeśli chcesz, aby jQuery przetwarzało wszystkie elementy svg w Twojej DOM, a Twój DOM ma rozsądny rozmiar. Ale jeśli twój DOM jest duży i zdecydujesz się na dynamiczne ładowanie jego części, naprawdę nie ma sensu ponowne skanowanie całego DOM tylko w celu aktualizacji elementów svg. Zamiast tego użyj wtyczki jQuery, aby to zrobić:

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

W html określ element svg w następujący sposób:

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

I zastosuj wtyczkę:

$(".mySVGClass").svgLoader();
AndroidDev
źródło
Tak, z pewnością są bardziej wydajne sposoby wykorzystania kodu, który podałem. Oto, w jaki sposób faktycznie używamy go w zakładach produkcyjnych. Buforuje pliki SVG! github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
1

dla animacji zdarzeń: najechanie my możemy pozostawić style wewnątrz pliku svg, np

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

sprawdź to na svgshare

getta
źródło