这是我提出的一段方便的代码的自我问答。

目前,还没有一种简单的方法来嵌入SVG图像,然后通过CSS访问SVG元素。使用JS SVG框架有多种方法,但如果您所做的只是制作一个带有翻转状态的简单图标,那么这些方法就过于复杂了。

所以这就是我想到的,我认为这是迄今为止在网站上使用SVG文件的最简单的方法。它的概念来自于早期的文本到图像替换方法,但据我所知,还从未用于svg。

问题是这样的:

我如何在CSS中嵌入SVG并改变其颜色而不使用JS-SVG框架?


当前回答

我知道你想用CSS来完成这个,但只是一个提醒,以防它是一个小的,简单的图像-你可以随时在notepad++中弹出它,并更改路径/whatever元素的填充:

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

@Drew Baker给出了一个很好的解决方案。代码正常工作。然而,那些使用AngularJs的人可能会发现很多依赖于jQuery。因此,我认为为AngularJS用户粘贴@Drew Baker的解决方案的代码是个好主意。

AngularJs的相同代码

1. Html:在你的Html文件中使用bellow标签:

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

2. Directive:这将是你需要识别标签的指令:

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

这是一个没有框架的代码,只有纯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)
        })

您现在可以在大多数现代浏览器(包括Edge,但不包括IE11)中使用CSS filter属性。它适用于SVG图像和其他元素。您可以使用色调旋转或反转来修改颜色,尽管它们不允许您单独修改不同的颜色。我使用下面的CSS类来显示一个图标的“禁用”版本(其中原始是一个饱和颜色的SVG图片):

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

这使得它在大多数浏览器中呈浅灰色。在IE中(可能还有我没有测试过的Opera Mini),它会因为不透明属性而明显褪色,尽管不是灰色,但看起来仍然很不错。

下面是Twemoji铃铛图标的四个不同CSS类的示例:original(黄色)、上面的“disabled”类、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>

首先,在HTML中使用IMG标记来嵌入SVG图形。我使用Adobe Illustrator来制作图形。

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

这就像你如何嵌入一个普通的图像。注意,您需要将IMG设置为svg类。“社会链接”类只是举个例子。ID不是必需的,但很有用。

然后使用jQuery代码(在单独的文件中或内联在HEAD中)。

    /**
     * Replace all SVG images with inline SVG
     */
        jQuery('img.svg').each(function(){
            var $img = jQuery(this);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

            jQuery.get(imgURL, function(data) {
                // Get the SVG tag, ignore the rest
                var $svg = jQuery(data).find('svg');

                // Add replaced image'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');

        });

上面的代码所做的是查找所有带有“svg”类的IMG,并将其替换为链接文件中的内联svg。最大的优势是它允许你现在使用CSS来改变SVG的颜色,如下所示:

svg:hover path {
    fill: red;
}

我编写的jQuery代码还跨原始图像ID和类进行移植。所以这个CSS也可以工作:

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

Or:

.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