How to change color of SVG image using CSS (jQuery SVG image replacement)?

后端 未结 17 1954
死守一世寂寞
死守一世寂寞 2020-11-21 17:36

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 vi

相关标签:
17条回答
  • 2020-11-21 17:51

    for :hover event animations we can left the styles inside svg file, like a

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

    check this on svgshare

    0 讨论(0)
  • 2020-11-21 17:54

    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');
        });
    });
    
    0 讨论(0)
  • 2020-11-21 17:55

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

    Explanation:

    I'm assuming you have html something like this:

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

    Definitely go the filter route, ie. your svg is most likely black or white. You can apply a filter to get it to be whatever color you want, for example, I have a black svg that I want mint green. I first invert it to be white (which is technically all RGB colors on full) then play with the hue saturation etc. To get it right:

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

    Even better is that you could just use a tool to convert the hex you want into a filter for you: https://codepen.io/sosuke/pen/Pjoqqp

    0 讨论(0)
  • 2020-11-21 18:00

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

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

    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.

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

    0 讨论(0)
  • 2020-11-21 18:00

    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.


    E.g.

    @font-face {
        font-family: 'iconFont';
        src: url('iconFont.eot');
    }
    #target{
        color: white;
        font-size:96px;
        font-family:iconFont;
    }
    
    0 讨论(0)
  • 2020-11-21 18:02

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

    AngularJs way of the same code

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

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

    '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 with 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]);
      });
    });
    
    0 讨论(0)
提交回复
热议问题