Làm cách nào để thay đổi màu sắc của hình ảnh SVG bằng CSS (thay thế hình ảnh SVG của jQuery)?


437

Đây là một câu hỏi và trả lời về một đoạn mã tiện dụng mà tôi đã nghĩ ra.

Hiện tại, không có cách nào dễ dàng để nhúng hình ảnh SVG và sau đó có quyền truy cập vào các yếu tố SVG thông qua CSS. Có nhiều phương pháp sử dụng các khung công tác JS SVG, nhưng chúng quá phức tạp nếu tất cả những gì bạn đang làm là tạo một biểu tượng đơn giản với trạng thái cuộn qua.

Vì vậy, đây là những gì tôi nghĩ ra, mà tôi nghĩ là cách dễ nhất để sử dụng các tệp SVG trên một trang web. Nó lấy khái niệm của nó từ các phương pháp thay thế văn bản thành hình ảnh ban đầu, nhưng theo như tôi biết thì chưa bao giờ được thực hiện cho các SVG.

Đây là câu hỏi:

Làm cách nào để tôi nhúng một SVG và thay đổi màu sắc của nó trong CSS mà không cần sử dụng khung công tác JS-SVG?


1
Thật không may, thẻ img không hoạt động với các tệp svg trong IE, vì vậy hãy nhớ rằng. IE nhận ra các thẻ nhúng. Dù sao, công việc tốt!

2
Đối với svg, bạn nên sử dụng thuộc tính css "điền". Đối với hình ảnh, nó phù hợp để sử dụng "bộ lọc". "Bộ lọc" thực tế hoạt động cho cả hai nhưng không cần thiết phải thực hiện tất cả công việc đó cho đồ họa vector.
Samy Bencherif

Câu trả lời:


536

Đầu tiên, sử dụng thẻ IMG trong HTML của bạn để nhúng đồ họa SVG. Tôi đã sử dụng Adobe Illustrator để làm đồ họa.

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

Điều này giống như cách bạn nhúng một hình ảnh bình thường. Lưu ý rằng bạn cần thiết lập IMG để có một lớp svg. Lớp 'liên kết xã hội' chỉ là ví dụ vì lợi ích. ID không bắt buộc, nhưng rất hữu ích.

Sau đó, sử dụng mã jQuery này (trong một tệp riêng hoặc nội tuyến trong CHÍNH).

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

        });

Những gì đoạn mã trên thực hiện là tìm kiếm tất cả các IMG với lớp 'svg' và thay thế nó bằng SVG nội tuyến từ tệp được liên kết. Ưu điểm lớn là nó cho phép bạn sử dụng CSS để thay đổi màu sắc của SVG, như vậy:

svg:hover path {
    fill: red;
}

Mã jQuery tôi đã viết cũng cổng trên ID và các lớp hình ảnh gốc. Vì vậy, CSS này cũng hoạt động:

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

Hoặc là:

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

Bạn có thể xem một ví dụ về nó hoạt động ở đây: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Chúng tôi có một phiên bản phức tạp hơn bao gồm bộ nhớ đệm ở đây: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90


6
Đôi khi, nó có thể không hoạt động trong Safari (ví dụ), để đảm bảo dữ liệu được trả về có thể đọc được, hãy thay thế });$ .get với}, 'xml');
Joan

29
Bạn thậm chí có thể thay thế bộ chọn bằng img[src$=".svg"]và loại bỏ sự cần thiết của svglớp.
Casey Chu

2
@LeonGaban Tôi không nghĩ có một cách để nhắm mục tiêu điền vào hình nền. Nó sẽ là siêu hữu ích nếu bạn có thể mặc dù!
Drew Baker

3
Một chút muộn, @LeonGaban, nhưng một cách tốt hơn để làm điều đó có lẽ là loại bỏ hoàn toàn thuộc tính điền và dựa vào một tệp CSS để thêm một điền vào phụ huynh. $('#ico_company path').removeAttr('fill'). Sau đó, bạn có thể làm #ico_company { fill: #ccc }trong tệp CSS của mình
bioball

2
@Soaku thật dễ dàng để jQuery đặt tất cả các đường dẫn giống như màu phông chữ đang làm một cái gì đó như `var color = $ img.closest ('p'). Css ('color'); $ svg.find ('đường dẫn'). attr ('điền', màu); `Nhưng tôi nghĩ rằng đây là một công việc tốt hơn để lại cho CSS.
Drew Baker

56

Phong cách

svg path {
    fill: #000;
}

Kịch bản

$(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
Nếu bạn không có attr chiều rộng, nó chỉ tạo một cái có số sai. width="170.667"trong trường hợp của tôi
stallingOne

2
Điều này không hoàn hảo vì nó mất kích thước img trước đó.
RichieHH

Xin chào, giả sử tôi có các Svg khác nhau với mỗi màu differnet. Sử dụng phương pháp này, tất cả các màu svg của tôi trở nên giống với các Svg đầu tiên đang được lặp. Bất cứ ý tưởng làm thế nào tôi có thể điều động xung quanh này để mỗi màu vẫn giữ nguyên như trước?
tnkh

1
lưu ý rằng nếu Svg của bạn cũng được tạo từ các pathhình không (như rect), bạn cũng cần xử lý chúng trong css
Mugen

33

Bây giờ bạn có thể sử dụng CSS filtersở hữu trong hầu hết các trình duyệt hiện đại (bao gồm Edge, nhưng không IE11). Nó hoạt động trên hình ảnh SVG cũng như các yếu tố khác. Bạn có thể sử dụng hue-rotatehoặc invertsửa đổi màu sắc, mặc dù chúng không cho phép bạn sửa đổi các màu khác nhau một cách độc lập. Tôi sử dụng lớp CSS sau để hiển thị phiên bản "bị vô hiệu hóa" của một biểu tượng (trong đó bản gốc là hình ảnh SVG với màu bão hòa):

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

Điều này làm cho nó màu xám nhạt trong hầu hết các trình duyệt. Trong IE (và có lẽ là Opera Mini, mà tôi chưa thử nghiệm), nó bị mờ đi đáng kể bởi thuộc tính độ mờ, trông vẫn khá tốt, mặc dù nó không có màu xám.

Dưới đây là một ví dụ với bốn lớp CSS khác nhau cho biểu tượng chuông Twemoji : ban đầu (màu vàng), lớp "bị vô hiệu hóa" ở trên, hue-rotate(màu xanh lá cây) và invert(màu xanh).


Chỉ cần lưu ý rằng đảo ngược là giải pháp tốt nếu bạn không muốn tạo phông chữ biểu tượng. Tôi đã sử dụng mã jQuery này để thay đổi biểu tượng trong tiêu đề trang web của mình theo thuộc tính màu css (lưu ý rằng tôi đang sử dụng biểu tượng png trắng):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

Cách tiếp cận tuyệt vời. Đã chỉnh sửa xml SVG của tôi để thêm màu biểu tượng đích sau đó sử dụng lớp bị vô hiệu hóa .icon để tô màu xám.
SushiGuy

Lưu ý rằng Explores cũ không hỗ trợ bộ lọc: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe

25

Ngoài ra, bạn có thể sử dụng CSS mask, hỗ trợ trình duyệt được cấp không tốt nhưng bạn có thể sử dụng dự phòng

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

14
MDN chỉ định rằng -webkit-maskkhông nên được sử dụng trên bất kỳ trang web sản xuất nào.
vaindil

1
không tô màu cho Svg
vishal

Có lẽ nó có liên quan để nói rằng bây giờ, bốn năm sau, giải pháp này đang hoạt động trong tất cả các trình duyệt chính. Chỉ cần thử nghiệm ở đây và nó 100% ok.
Daniel Leme

23

Nếu bạn có thể bao gồm các tệp (PHP bao gồm hoặc bao gồm thông qua CMS bạn chọn) trong trang của bạn, bạn có thể thêm mã SVG và đưa nó vào trang của mình. Điều này hoạt động tương tự như dán nguồn SVG vào trang, nhưng làm cho đánh dấu trang sạch hơn.

Lợi ích là bạn có thể nhắm mục tiêu các phần của SVG thông qua CSS để di chuột - không yêu cầu javascript.

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

Bạn chỉ cần sử dụng quy tắc CSS như thế này:

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

Lưu ý rằng !importantbit là cần thiết để ghi đè màu tô.


3
Đối với những người sử dụng AngularJS:<div ng-include="'svg.svg'"></div>
Mikel

Không phải là một giải pháp rất thanh lịch lưu trữ dữ liệu svg trong cơ sở dữ liệu. Không sai, nhưng việc bơm ra dữ liệu DOM xml / html / svg từ API hoặc CMS thay vì sử dụng các mẫu hoặc các tài sản khác chỉ cảm thấy sai.
ChristoKiwi

Cảm ơn bạn đã đóng góp này ... Các trang web tiên tiến nhất hiện nay lồng dữ liệu svg để cho phép tất cả các loại hoạt động, mà không có câu trả lời này, tôi sẽ không đoán được điều đó!
webman

Ngoài ra, nếu SVG của bạn có các khu vực trong suốt, những vùng này sẽ không được tính là lơ lửng và bạn có thể gặp "di chuột hào nhoáng". Để khắc phục điều đó, chỉ cần thêm phần tử trình bao bọc (<a>, nếu thuận tiện) và sau đó thêm phần tử đó vào quy tắc CSS. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }Hoặc thậm chí chỉ cần loại bỏ di chuột ban đầu của đường dẫn SVG vì dù sao bạn cũng đang nhắm mục tiêu nó thông qua phần tử trình bao bọc.
Neil Monroe

18

@Drew Baker đã đưa ra một giải pháp tuyệt vời để giải quyết vấn đề. Mã hoạt động đúng. Tuy nhiên, những người sử dụng AngularJs có thể tìm thấy rất nhiều sự phụ thuộc vào jQuery. Do đó, tôi nghĩ rằng nên dán cho người dùng AngularJS, một mã theo giải pháp của @Drew Baker.

Cách AngularJs của cùng một mã

1. Html : sử dụng thẻ dưới đây trong tệp html của bạn:

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

2. Chỉ thị : đây sẽ là chỉ thị mà bạn sẽ cần nhận ra thẻ:

'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. Bài kiểm tra đơn vị với karma-hoa nhài :

'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
giải pháp của bạn không hiệu quả, có thể là<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent

@guillaumevincent nếu bạn muốn sử dụng nó ng-includethì chỉ cần thay đổi dòng này var imgURL = element.attr('src');thànhvar imgURL = element.attr('ng-include');
Tối đa

Đây là một giải pháp rất tiện dụng, nhưng hãy cẩn thận trong việc lạm dụng nó vì nó có thể ảnh hưởng đến hiệu năng khá khó khăn - IE một bộ 5 biểu tượng chia sẻ được lặp lại trên một danh sách bài viết hoặc một cái gì đó tương tự.
skxc 11/03/2015

1
Có một vấn đề với mã của bạn trong IE. Bạn có thể sử dụng chỉ if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }thay vì chia và vòng lặp.
Robert Bokori

2
Công việc tuyệt vời Nhưng đối với một số hình ảnh nhất định, bạn cần lấy phần tử đầu tiên của svg ( angular.element(data)[0];) và để nó hoạt động với IE sử dụng if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. Ngoài ra, bạn có thể muốn thêm cache: truevào các tùy chọn $http.getnếu không trang của bạn có thể trở nên rất chậm.
leo

16

Tôi nhận ra rằng bạn muốn thực hiện điều này bằng CSS, nhưng chỉ là một lời nhắc trong trường hợp đó là một hình ảnh nhỏ, đơn giản - bạn luôn có thể mở nó trong Notepad ++ và thay đổi đường dẫn / bất cứ điều gì:

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

Nó có thể tiết kiệm được một tấn kịch bản xấu xí. Xin lỗi nếu nó không đúng, nhưng đôi khi các giải pháp đơn giản có thể bị bỏ qua.

... thậm chí hoán đổi nhiều hình ảnh svg có thể có kích thước nhỏ hơn một số đoạn mã cho câu hỏi này.


7

Tôi đã viết một chỉ thị để giải quyết vấn đề này với AngularJS. Nó có sẵn ở đây - ngReustomSvg .

Nó thay thế phần tử SVG sau khi được hiển thị và đặt nó bên trong một divphần tử, làm cho CSS của nó dễ dàng thay đổi. Điều này giúp sử dụng cùng một tệp SVG ở những nơi khác nhau bằng các kích cỡ / màu sắc khác nhau.

Cách sử dụng rất đơn giản:

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

Sau đó, bạn có thể dễ dàng có:

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

Xin chào, cảm ơn vì đã cung cấp giải pháp này. Tôi đã thử nó và nó mang lại: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[object SVGSVGEuity]] </ div> Trong html, sau đó chỉ cần đặt [[object SVGSVGEuity]]. Bạn có biết vấn đề là gì không? Một câu hỏi khác, nó có ảnh hưởng lớn đến hiệu suất hay tôi có thể sử dụng nó trên nhiều svg trên một trang không? Và cuối cùng, nó vẫn nằm trên góc 1.3 (bower).
phiền

Phiên bản góc nào bạn đang sử dụng? Không gặp phải vấn đề của bạn .. có lẽ đó là điều gì đó với SVG? Hiệu suất của công tắc tương đối nặng, tôi đã tự mình sử dụng nó vào khoảng 10 và nó vẫn ổn .. Tôi đoán điều đó phụ thuộc vào số lượng / kích thước, vì vậy hãy dùng thử và thử nghiệm với nó. Có vấn đề gì với người cung cấp? Bạn đang sử dụng một phiên bản khác và có xung đột?
Omri Aharon

5

TL / DR: ĐI tại đây-> https://codepen.io/sosuke/pen/Pjoqqp

Giải trình:

Tôi giả sử bạn có html như thế này:

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

Chắc chắn đi theo tuyến đường lọc, tức là. Svg của bạn rất có thể là màu đen hoặc trắng. Bạn có thể áp dụng bộ lọc để biến nó thành bất kỳ màu nào bạn muốn, ví dụ: tôi có một màu đen mà tôi muốn màu xanh bạc hà. Trước tiên tôi đảo ngược nó thành màu trắng (về mặt kỹ thuật là tất cả các màu RGB đầy đủ) sau đó chơi với độ bão hòa màu sắc, v.v ... Để làm cho đúng:

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

Thậm chí tốt hơn là bạn chỉ có thể sử dụng một công cụ để chuyển đổi hex bạn muốn thành bộ lọc cho bạn: https://codepen.io/sosuke/pen/Pjoqqp


Đây là một giải pháp chỉ css tuyệt vời, cộng với codepen từ hex đến bộ lọc là tuyệt vời.
Richi González

4

Đây là phiên bản knockout.jsdựa trên câu trả lời được chấp nhận:

Quan trọng: Nó thực sự yêu cầu jQuery thay thế, nhưng tôi nghĩ nó có thể hữu ích với một số người.

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

        }
    };

Sau đó, chỉ cần áp dụng data-bind="svgConvert: true"cho thẻ img của bạn.

Giải pháp này thay thế hoàn toàn imgthẻ bằng SVG và mọi ràng buộc bổ sung sẽ không được tôn trọng.


2
Điều đó thật tuyệt! Nếu bạn muốn đưa nó lên cấp độ tiếp theo, chúng tôi có một phiên bản cập nhật bao gồm bộ đệm, do đó, cùng một SVG không được yêu cầu hai lần. github.com/funkhaus/style-guide/blob/master/template/js/iêu
Drew Baker

Tôi đã có một chút lo lắng về điều đó nhưng bản thân tôi không có thời gian để xem xét nó. Chỉ cần một cái gì đó nhanh chóng
Simon_Weaver

1
@DrewBaker thực sự tôi đã quan tâm nhiều hơn rằng thẻ img sẽ yêu cầu tệp và sau đó getsẽ yêu cầu lại. Tôi coi việc thay đổi srcmột data-srcthuộc tính trên imgthẻ, nhưng kết luận rằng các trình duyệt hiện đại là đủ lẽ thông minh để cache file nào
Simon_Weaver

3

Đây không phải là mã khung, chỉ có js thuần túy:

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

Có một thư viện mã nguồn mở có tên là SVGInject sử dụng onloadthuộc tính để kích hoạt phép tiêm. Bạn có thể tìm thấy dự án GitHub tại https://github.com/iconfu/svg-inject

Dưới đây là một ví dụ tối thiểu sử dụng SVGInject:

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

Sau khi hình ảnh được tải, onload="SVGInject(this)sẽ kích hoạt tiêm và <img>phần tử sẽ được thay thế bằng nội dung của tệp SVG được cung cấp trong srcthuộc tính.

Nó giải quyết một số vấn đề với tiêm SVG:

  1. SVG có thể được ẩn cho đến khi tiêm xong. Điều này rất quan trọng nếu một kiểu đã được áp dụng trong thời gian tải, điều này sẽ gây ra một "flash nội dung không được lưu trữ" ngắn.

  2. Các <img>yếu tố tiêm tự động. Nếu bạn thêm SVG một cách linh hoạt, bạn không phải lo lắng về việc gọi lại chức năng tiêm.

  3. Một chuỗi ngẫu nhiên được thêm vào mỗi ID trong SVG để tránh có cùng một ID nhiều lần trong tài liệu nếu một SVG được tiêm nhiều lần.

SVGInject là Javascript đơn giản và hoạt động với tất cả các trình duyệt hỗ trợ SVG.

Tuyên bố miễn trừ trách nhiệm: Tôi là đồng tác giả của SVGInject


1
Tôi thích giải pháp này nhất, vì nó quan tâm đến các SVG được thêm động.
VickyB

2

Nếu chúng ta có số lượng lớn hơn các hình ảnh svg như vậy, chúng ta cũng có thể nhờ sự trợ giúp của các tệp phông chữ.
Các trang web như https://glyphter.com/ có thể cung cấp cho chúng tôi một tệp phông chữ từ các Svss của chúng tôi.


Ví dụ

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

5
Cá nhân tôi ghét kỹ thuật "hình ảnh như một phông chữ". Nó làm cho nó khó khăn để thêm / chỉnh sửa hình ảnh, thêm rất nhiều đánh dấu vô nghĩa. Phông chữ phải là phông chữ, hình ảnh phải là hình ảnh, v.v.
Drew Baker

Đã đồng ý. Bạn cũng cần nhớ / tra cứu các hình ảnh được gán cho các ký tự. nhưng đối với trường hợp cụ thể trong đó hình ảnh được sử dụng làm biểu tượng / nút / dấu đầu dòng, hoạt động như văn bản hơn phương tiện, tập tin phông chữ cũng có thể là một lựa chọn thay thế
Abhishek Borar

thậm chí github không sử dụng phông chữ nữa cho biểu tượng github.com/blog/2112-delivering-octicons-with-svg
gagarine

2

Bạn có thể sử dụng dữ liệu hình ảnh cho điều đó. bằng cách sử dụng dữ liệu hình ảnh (data-URI), bạn có thể truy cập SVG như nội tuyến.

Đây là hiệu ứng cuộn qua sử dụng CSS và SVG thuần túy.

Tôi biết nó lộn xộn nhưng bạn có thể làm theo cách này.

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

Bạn có thể chuyển đổi svg của bạn sang url dữ liệu tại đây

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

Điều này sẽ không hoạt động đối với các SVG phức tạp khi bạn chỉ muốn một số đường dẫn / đa giác / vv .. nhất định thay đổi khi di chuột phải không?
Drew Baker

Không bạn có thể..nhưng nó rất phức tạp
patelarpan

Nó chỉ là giải pháp cho biểu tượng
patelarpan

Nếu một số làm việc với biểu tượng. Sau đó, nó tuyệt vời. Bootstrap 4 cũng sử dụng kỹ thuật này
patelarpan

2

Vì SVG về cơ bản là mã, bạn chỉ cần nội dung. Tôi đã sử dụng PHP để có được nội dung, nhưng bạn có thể sử dụng bất cứ thứ gì bạn muốn.

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

Sau đó, tôi đã in nội dung "như là" bên trong một thùng chứa div

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

Để hoàn thiện quy tắc đặt các con SVG của CSS trên CSS

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

Tôi đã nhận được kết quả này với một biểu tượng vật chất SVG:

  1. Mozilla Firefox 59.0.2 (64-bit) Linux

nhập mô tả hình ảnh ở đây

  1. Google Chrome66.0.3359.181 (Xây dựng chính thức) (64 bit) Linux

nhập mô tả hình ảnh ở đây

  1. Opera 53.0.2907.37 Linux

nhập mô tả hình ảnh ở đây


1

Giải pháp được chọn là ổn nếu bạn muốn jQuery xử lý tất cả các phần tử svg trong DOM của bạn và DOM của bạn có kích thước hợp lý. Nhưng nếu DOM của bạn lớn và bạn quyết định tải các phần của DOM một cách linh hoạt, thì thực sự vô nghĩa khi phải quét lại toàn bộ DOM chỉ để cập nhật các phần tử svg. Thay vào đó, hãy sử dụng plugin jQuery để làm điều này:

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

Trong html của bạn, chỉ định một phần tử svg như sau:

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

Và áp dụng plugin:

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

Vâng, chắc chắn có nhiều cách hiệu quả hơn để sử dụng mã tôi đã đưa ra. Đây là cách chúng tôi thực sự sử dụng nó trên các trang web sản xuất. Nó lưu trữ SVG! github.com/funkhaus/style-guide/blob/master/template/js/iêu
Drew Baker

1

cho: hoạt hình sự kiện di chuột, chúng ta có thể để các kiểu bên trong tệp svg, như một

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

kiểm tra cái này trên svgshare

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.