如何使用CSS (jQuery SVG图像替换)改变SVG图像的颜色?

时间:2022-11-21 12:15:35

This is a self Q&A of a handy piece of code I came up with.

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

Currently, there isn't an easy way to embed an SVG image and then have access to the SVG elements via CSS. There are various methods of using JS SVG frameworks, but they are overly complicated if all you are doing is making a simple icon with a rollover state.

目前,没有一种简单的方法可以嵌入SVG图像,然后通过CSS访问SVG元素。有很多使用JS SVG框架的方法,但是如果您所做的只是用一个翻转的状态创建一个简单的图标,那么它们就会变得过于复杂。

So here is what I came up with, which I think is by far the easiest way to use SVG files on a website. It takes its concept from the early text-to-image replacement methods, but as far as I am aware has never been done for SVGs.

这就是我想到的,我认为这是目前在网站上使用SVG文件最简单的方法。它的概念从早期的文本到图像替换方法,但就我所知,从来没有为SVGs做过。

This is the question:

这是一个问题:

How do I embed an SVG and change its color in CSS without using a JS-SVG framework?

13 个解决方案

#1


489  

Firstly, use an IMG tag in your HTML to embed an SVG graphic. I used Adobe Illustrator to make the graphic.

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

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

This is just like how you'd embed a normal image. Note that you need to set the IMG to have a class of svg. The 'social-link' class is just for examples sake. The ID is not required, but is useful.

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

Then use this jQuery code (in a separate file or inline in the HEAD).

然后使用这个jQuery代码(在单独的文件中或在头部内嵌)。

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

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

                // Add replaced image's ID to the new SVG
                if(typeof imgID !== 'undefined') {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if(typeof imgClass !== 'undefined') {
                    $svg = $svg.attr('class', imgClass+' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        });

What the above code does is look for all IMG's with the class 'svg' and replace it with the inline SVG from the linked file. The massive advantage is that it allows you to use CSS to change the color of the SVG now, like so:

上面的代码所做的是查找所有IMG的“svg”,并将其替换为来自链接文件的内嵌svg。它的巨大优势在于它允许您使用CSS来改变SVG的颜色,比如:

svg:hover path {
    fill: red;
}

The jQuery code I wrote also ports across the original images ID and classes. So this CSS works too:

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

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

Or:

或者:

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

You can see an example of it working here: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

你可以在这里看到它的一个例子:http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html。

We have a more complicated version that includes caching here: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

我们有一个更复杂的版本,其中包括缓存:https://github.com/funkhaus/styleguide/blob/master/template/js/site.js #L32-L90。

#2


42  

Style

风格

svg path {
    fill: #000;
}

Script

脚本

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

#3


23  

Alternatively you could use CSS mask, granted browser support isn't good but you could use a fallback

另外,你也可以使用CSS mask,虽然浏览器的支持不是很好,但是你可以使用回退。

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

#4


20  

If you can include files (PHP include or include via your CMS of choice) in your page, you can add the SVG code and include it into your page. This works the same as pasting the SVG source into the page, but makes the page markup cleaner.

如果您可以在页面中包含文件(PHP包含或包含在您的CMS中),您可以添加SVG代码并将其包含到您的页面中。这与将SVG源代码粘贴到页面中相同,但使页面标记更干净。

The benefit is that you can target parts of your SVG via CSS for hover -- no javascript required.

这样做的好处是可以通过CSS对SVG的部分进行悬停——不需要javascript。

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

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

You just have to use a CSS rule like this:

你只需要使用这样的CSS规则:

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

Note that the !important bit is necessary to override the fill color.

注意!重要的部分是覆盖填充颜色所必需的。

#5


18  

@Drew Baker gave a great solution to solve the problem. The code works properly. However, those who uses AngularJs may find lots of dependency on jQuery. Consequently, I thought it is a good idea to paste for AngularJS users, a code following @Drew Baker's solution.

drew Baker提出了一个解决这个问题的好办法。代码能正常工作。然而,使用AngularJs的人可能会发现大量依赖于jQuery。因此,我认为对AngularJS用户进行粘贴是一个不错的主意,下面的代码是@Drew Baker的解决方案。

AngularJs way of the same code

相同代码的AngularJs方法。

1. Html: use the bellow tag in you html file:

1。Html:在Html文件中使用bellow标签:

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

2. Directive: this will be the directive that you will need to recognise the tag:

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

'use strict';
angular.module('myApp')
  .directive('svgImage', ['$http', function($http) {
    return {
      restrict: 'E',
      link: function(scope, element) {
        var imgURL = element.attr('src');
        // if you want to use ng-include, then
        // instead of the above line write the bellow:
        // var imgURL = element.attr('ng-include');
        var request = $http.get(
          imgURL,
          {'Content-Type': 'application/xml'}
        );

        scope.manipulateImgNode = function(data, elem){
          var $svg = angular.element(data)[4];
          var imgClass = elem.attr('class');
          if(typeof(imgClass) !== 'undefined') {
            var classes = imgClass.split(' ');
            for(var i = 0; i < classes.length; ++i){
              $svg.classList.add(classes[i]);
            }
          }
          $svg.removeAttribute('xmlns:a');
          return $svg;
        };

        request.success(function(data){
          element.replaceWith(scope.manipulateImgNode(data, element));
        });
      }
    };
  }]);

3. CSS:

3所示。CSS:

.any-class-you-wish{
    border: 1px solid red;
    height: 300px;
    width:  120px
}

4. Unit-test with karma-jasmine:

4所示。与karma-jasmine单元测试:

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

#6


16  

You can now use the CSS filter property in most modern browsers (including Edge, but not IE11). It works on SVG images as well as other elements. You can use hue-rotate or invert to modify colors, although they don't let you modify different colors independently. I use the following CSS class to show a "disabled" version of an icon (where the original is an SVG picture with saturated color):

现在,您可以在大多数现代浏览器中使用CSS过滤属性(包括Edge,但不包括IE11)。它不仅适用于SVG图像,也适用于其他元素。您可以使用hue-rotate或invert来修改颜色,尽管它们不能独立地修改不同的颜色。我使用下面的CSS类来显示一个图标的“禁用”版本(原来是一个带有饱和颜色的SVG图片):

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

This makes it light grey in most browsers. In IE (and probably Opera Mini, which I haven't tested) it is noticeably faded by the opacity property, which still looks pretty good, although it's not grey.

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

Here's an example with four different CSS classes for the Twemoji bell icon: original (yellow), the above "disabled" class, hue-rotate (green), and invert (blue).

这里有一个例子,有四个不同的CSS类,用于Twemoji bell图标:原始(黄色)、上面的“禁用”类、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>

#7


7  

I wrote a directive to solve this issue with AngularJS. It is available here - ngReusableSvg.

我写了一个指令,用AngularJS解决这个问题。这里有- ngReusableSvg。

It replaces the SVG element after it's been rendered, and places it inside a div element, making its CSS easily changeable. This helps using the same SVG file in different places using different sizes/colors.

它在呈现后替换SVG元素,并将其放置在div元素中,使其CSS易于更改。这有助于在不同的地方使用不同的大小/颜色使用相同的SVG文件。

The usage is simple:

使用很简单:

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

After that, you can easily have:

在那之后,你可以很容易地拥有:

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

#8


3  

If we have a greater number of such svg images we can also take the help of font-files.
Sites like https://glyphter.com/ can get us a font file from our svgs.

如果我们有更多的这样的svg图像,我们也可以借助于font-files。像https://glyphter.com/这样的网站可以从我们的svgs获得一个字体文件。


E.g.

如。

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

#9


3  

Here's a version for knockout.js based on the accepted answer:

这是击倒的版本。js基于公认的回答:

Important: It does actually require jQuery too for the replacing, but I thought it may be useful to some.

重要的是:它确实需要jQuery来替换,但是我认为它可能对一些人有用。

ko.bindingHandlers.svgConvert =
    {
        'init': function ()
        {
            return { 'controlsDescendantBindings': true };
        },

        'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var $img = $(element);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

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

                // Add replaced image's ID to the new SVG
                if (typeof imgID !== 'undefined')
                {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if (typeof imgClass !== 'undefined')
                {
                    $svg = $svg.attr('class', imgClass + ' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        }
    };

Then just apply data-bind="svgConvert: true" to your img tag.

然后将数据绑定="svgConvert: true"应用到img标签。

This solution completely replaces the img tag with a SVG and any additional bindings would not be respected.

这个解决方案完全用SVG替代img标签,任何附加的绑定都不会受到尊重。

#10


3  

Here's a no framework code, only pure js :

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

#11


3  

I realize you're wanting to accomplish this with CSS, but just a reminder in case it's a small, simple image - you can always pop it open in Notepad++ and change the path/whateverelement's fill:

我意识到你想用CSS来实现它,但只是提醒一下,如果它是一个小的,简单的图像——你可以在Notepad++中打开它,并改变路径/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"/>

It could save a ton of ugly script. Sorry if it's off-base, but sometimes the simple solutions can be overlooked.

它可以节省大量丑陋的脚本。不好意思,如果它是偏离基础的,但有时简单的解决方案可以被忽略。

...even swapping multiple svg images might be smaller in size than some of the code snippets for this question.

…甚至交换多个svg图像可能比这个问题的一些代码片段更小。

#12


1  

The selected solution is fine if you want jQuery to process all svg elements in your DOM and your DOM is of reasonable size. But if your DOM is large and you decide to load parts of your DOM dynamically, it really makes no sense to have to rescan the entire DOM just to update svg elements. Instead, use a jQuery plugin to do this:

如果您希望jQuery处理DOM中的所有svg元素,并且DOM具有合理的大小,那么选择的解决方案是可以接受的。但是,如果DOM很大,并且决定动态加载DOM的部分,那么必须重新扫描整个DOM以更新svg元素,这是毫无意义的。相反,可以使用jQuery插件来实现这一点:

/**
 * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents.
 *
 * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element).
 *
 * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object's
 * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place
 * any styles in a style class instead.
 */
(function ($) {
    $.fn.svgLoader = function () {
        var src = $(this).attr("src");
        var width = this.attr("width");
        var height = this.attr("height");
        var cls = this.attr("class");
        var ctx = $(this);

        // Get the svg file and replace the <svg> element.
        $.ajax({
            url: src,
            cache: false
        }).done(function (html) {
            let svg = $(html);
            svg.attr("width", width);
            svg.attr("height", height);
            svg.attr("class", cls);
            var newHtml = $('<a></a>').append(svg.clone()).html();
            ctx.replaceWith(newHtml);
        });

        return this;
    };

}(jQuery));

In your html, specify an svg element as follows:

在html中,指定svg元素如下:

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

And apply the plugin:

和应用插件:

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

#13


-2  

If this is a static change, then open the SVG file in Adobe Illustrator (or any suitable SVG editor) change the color and save it.

如果这是静态更改,那么在adobeillustrator(或任何合适的SVG编辑器)中打开SVG文件,更改颜色并保存它。

#1


489  

Firstly, use an IMG tag in your HTML to embed an SVG graphic. I used Adobe Illustrator to make the graphic.

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

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

This is just like how you'd embed a normal image. Note that you need to set the IMG to have a class of svg. The 'social-link' class is just for examples sake. The ID is not required, but is useful.

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

Then use this jQuery code (in a separate file or inline in the HEAD).

然后使用这个jQuery代码(在单独的文件中或在头部内嵌)。

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

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

                // Add replaced image's ID to the new SVG
                if(typeof imgID !== 'undefined') {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if(typeof imgClass !== 'undefined') {
                    $svg = $svg.attr('class', imgClass+' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        });

What the above code does is look for all IMG's with the class 'svg' and replace it with the inline SVG from the linked file. The massive advantage is that it allows you to use CSS to change the color of the SVG now, like so:

上面的代码所做的是查找所有IMG的“svg”,并将其替换为来自链接文件的内嵌svg。它的巨大优势在于它允许您使用CSS来改变SVG的颜色,比如:

svg:hover path {
    fill: red;
}

The jQuery code I wrote also ports across the original images ID and classes. So this CSS works too:

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

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

Or:

或者:

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

You can see an example of it working here: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

你可以在这里看到它的一个例子:http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html。

We have a more complicated version that includes caching here: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

我们有一个更复杂的版本,其中包括缓存:https://github.com/funkhaus/styleguide/blob/master/template/js/site.js #L32-L90。

#2


42  

Style

风格

svg path {
    fill: #000;
}

Script

脚本

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

#3


23  

Alternatively you could use CSS mask, granted browser support isn't good but you could use a fallback

另外,你也可以使用CSS mask,虽然浏览器的支持不是很好,但是你可以使用回退。

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

#4


20  

If you can include files (PHP include or include via your CMS of choice) in your page, you can add the SVG code and include it into your page. This works the same as pasting the SVG source into the page, but makes the page markup cleaner.

如果您可以在页面中包含文件(PHP包含或包含在您的CMS中),您可以添加SVG代码并将其包含到您的页面中。这与将SVG源代码粘贴到页面中相同,但使页面标记更干净。

The benefit is that you can target parts of your SVG via CSS for hover -- no javascript required.

这样做的好处是可以通过CSS对SVG的部分进行悬停——不需要javascript。

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

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

You just have to use a CSS rule like this:

你只需要使用这样的CSS规则:

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

Note that the !important bit is necessary to override the fill color.

注意!重要的部分是覆盖填充颜色所必需的。

#5


18  

@Drew Baker gave a great solution to solve the problem. The code works properly. However, those who uses AngularJs may find lots of dependency on jQuery. Consequently, I thought it is a good idea to paste for AngularJS users, a code following @Drew Baker's solution.

drew Baker提出了一个解决这个问题的好办法。代码能正常工作。然而,使用AngularJs的人可能会发现大量依赖于jQuery。因此,我认为对AngularJS用户进行粘贴是一个不错的主意,下面的代码是@Drew Baker的解决方案。

AngularJs way of the same code

相同代码的AngularJs方法。

1. Html: use the bellow tag in you html file:

1。Html:在Html文件中使用bellow标签:

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

2. Directive: this will be the directive that you will need to recognise the tag:

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

'use strict';
angular.module('myApp')
  .directive('svgImage', ['$http', function($http) {
    return {
      restrict: 'E',
      link: function(scope, element) {
        var imgURL = element.attr('src');
        // if you want to use ng-include, then
        // instead of the above line write the bellow:
        // var imgURL = element.attr('ng-include');
        var request = $http.get(
          imgURL,
          {'Content-Type': 'application/xml'}
        );

        scope.manipulateImgNode = function(data, elem){
          var $svg = angular.element(data)[4];
          var imgClass = elem.attr('class');
          if(typeof(imgClass) !== 'undefined') {
            var classes = imgClass.split(' ');
            for(var i = 0; i < classes.length; ++i){
              $svg.classList.add(classes[i]);
            }
          }
          $svg.removeAttribute('xmlns:a');
          return $svg;
        };

        request.success(function(data){
          element.replaceWith(scope.manipulateImgNode(data, element));
        });
      }
    };
  }]);

3. CSS:

3所示。CSS:

.any-class-you-wish{
    border: 1px solid red;
    height: 300px;
    width:  120px
}

4. Unit-test with karma-jasmine:

4所示。与karma-jasmine单元测试:

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

#6


16  

You can now use the CSS filter property in most modern browsers (including Edge, but not IE11). It works on SVG images as well as other elements. You can use hue-rotate or invert to modify colors, although they don't let you modify different colors independently. I use the following CSS class to show a "disabled" version of an icon (where the original is an SVG picture with saturated color):

现在,您可以在大多数现代浏览器中使用CSS过滤属性(包括Edge,但不包括IE11)。它不仅适用于SVG图像,也适用于其他元素。您可以使用hue-rotate或invert来修改颜色,尽管它们不能独立地修改不同的颜色。我使用下面的CSS类来显示一个图标的“禁用”版本(原来是一个带有饱和颜色的SVG图片):

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

This makes it light grey in most browsers. In IE (and probably Opera Mini, which I haven't tested) it is noticeably faded by the opacity property, which still looks pretty good, although it's not grey.

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

Here's an example with four different CSS classes for the Twemoji bell icon: original (yellow), the above "disabled" class, hue-rotate (green), and invert (blue).

这里有一个例子,有四个不同的CSS类,用于Twemoji bell图标:原始(黄色)、上面的“禁用”类、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>

#7


7  

I wrote a directive to solve this issue with AngularJS. It is available here - ngReusableSvg.

我写了一个指令,用AngularJS解决这个问题。这里有- ngReusableSvg。

It replaces the SVG element after it's been rendered, and places it inside a div element, making its CSS easily changeable. This helps using the same SVG file in different places using different sizes/colors.

它在呈现后替换SVG元素,并将其放置在div元素中,使其CSS易于更改。这有助于在不同的地方使用不同的大小/颜色使用相同的SVG文件。

The usage is simple:

使用很简单:

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

After that, you can easily have:

在那之后,你可以很容易地拥有:

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

#8


3  

If we have a greater number of such svg images we can also take the help of font-files.
Sites like https://glyphter.com/ can get us a font file from our svgs.

如果我们有更多的这样的svg图像,我们也可以借助于font-files。像https://glyphter.com/这样的网站可以从我们的svgs获得一个字体文件。


E.g.

如。

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

#9


3  

Here's a version for knockout.js based on the accepted answer:

这是击倒的版本。js基于公认的回答:

Important: It does actually require jQuery too for the replacing, but I thought it may be useful to some.

重要的是:它确实需要jQuery来替换,但是我认为它可能对一些人有用。

ko.bindingHandlers.svgConvert =
    {
        'init': function ()
        {
            return { 'controlsDescendantBindings': true };
        },

        'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var $img = $(element);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

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

                // Add replaced image's ID to the new SVG
                if (typeof imgID !== 'undefined')
                {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if (typeof imgClass !== 'undefined')
                {
                    $svg = $svg.attr('class', imgClass + ' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        }
    };

Then just apply data-bind="svgConvert: true" to your img tag.

然后将数据绑定="svgConvert: true"应用到img标签。

This solution completely replaces the img tag with a SVG and any additional bindings would not be respected.

这个解决方案完全用SVG替代img标签,任何附加的绑定都不会受到尊重。

#10


3  

Here's a no framework code, only pure js :

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

#11


3  

I realize you're wanting to accomplish this with CSS, but just a reminder in case it's a small, simple image - you can always pop it open in Notepad++ and change the path/whateverelement's fill:

我意识到你想用CSS来实现它,但只是提醒一下,如果它是一个小的,简单的图像——你可以在Notepad++中打开它,并改变路径/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"/>

It could save a ton of ugly script. Sorry if it's off-base, but sometimes the simple solutions can be overlooked.

它可以节省大量丑陋的脚本。不好意思,如果它是偏离基础的,但有时简单的解决方案可以被忽略。

...even swapping multiple svg images might be smaller in size than some of the code snippets for this question.

…甚至交换多个svg图像可能比这个问题的一些代码片段更小。

#12


1  

The selected solution is fine if you want jQuery to process all svg elements in your DOM and your DOM is of reasonable size. But if your DOM is large and you decide to load parts of your DOM dynamically, it really makes no sense to have to rescan the entire DOM just to update svg elements. Instead, use a jQuery plugin to do this:

如果您希望jQuery处理DOM中的所有svg元素,并且DOM具有合理的大小,那么选择的解决方案是可以接受的。但是,如果DOM很大,并且决定动态加载DOM的部分,那么必须重新扫描整个DOM以更新svg元素,这是毫无意义的。相反,可以使用jQuery插件来实现这一点:

/**
 * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents.
 *
 * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element).
 *
 * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object's
 * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place
 * any styles in a style class instead.
 */
(function ($) {
    $.fn.svgLoader = function () {
        var src = $(this).attr("src");
        var width = this.attr("width");
        var height = this.attr("height");
        var cls = this.attr("class");
        var ctx = $(this);

        // Get the svg file and replace the <svg> element.
        $.ajax({
            url: src,
            cache: false
        }).done(function (html) {
            let svg = $(html);
            svg.attr("width", width);
            svg.attr("height", height);
            svg.attr("class", cls);
            var newHtml = $('<a></a>').append(svg.clone()).html();
            ctx.replaceWith(newHtml);
        });

        return this;
    };

}(jQuery));

In your html, specify an svg element as follows:

在html中,指定svg元素如下:

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

And apply the plugin:

和应用插件:

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

#13


-2  

If this is a static change, then open the SVG file in Adobe Illustrator (or any suitable SVG editor) change the color and save it.

如果这是静态更改,那么在adobeillustrator(或任何合适的SVG编辑器)中打开SVG文件,更改颜色并保存它。