本文翻译自:How to change color of SVG image using CSS (jQuery SVG image replacement)?
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. 当前,没有一种简单的方法可以嵌入SVG图像,然后可以通过CSS访问SVG元素。 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. 有多种使用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. 所以这就是我想出的,我认为这是迄今为止在网站上使用SVG文件的最简单方法。 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进行过处理。
This is the question: 这是问题:
参考:https://stackoom.com/question/oGHb/如何使用CSS更改SVG图像的颜色-jQuery-SVG图像替换
Firstly, use an IMG tag in your HTML to embed an SVG graphic. 首先,在HTML中使用IMG标签嵌入SVG图形。 I used Adobe Illustrator to make the graphic. 我使用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. 请注意,您需要将IMG设置为具有svg类。 The 'social-link' class is just for examples sake. 'social-link'类仅出于示例目的。 The ID is not required, but is useful. 该ID不是必需的,但很有用。
Then use this jQuery code (in a separate file or inline in the HEAD). 然后使用此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');
});
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. 上面的代码所做的是查找所有带有“ svg”类的IMG,并将其替换为链接文件中的内联SVG。 The massive advantage is that it allows you to use CSS to change the color of the SVG now, like so: 巨大的优势在于,它允许您现在使用CSS来更改SVG的颜色,如下所示:
svg:hover path {
fill: red;
}
The jQuery code I wrote also ports across the original images ID and classes. 我编写的jQuery代码还跨越了原始图像ID和类。 So this CSS works too: 因此,此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/style-guide/blob/master/template/js/site.js#L32-L90
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. 如果您可以在页面中包含文件(PHP包含或通过选择的CMS包含),则可以添加SVG代码并将其包含到页面中。 This works the same as pasting the SVG source into the page, but makes the page markup cleaner. 这与将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. 请注意, !important
位对于覆盖填充颜色是必需的。
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;
}
@Drew Baker gave a great solution to solve the problem. @Drew Baker提供了一个很好的解决方案。 The code works properly. 该代码正常工作。 However, those who uses AngularJs may find lots of dependency on jQuery. 但是,使用AngularJs的人可能会发现很多对jQuery的依赖。 Consequently, I thought it is a good idea to paste for AngularJS users, a code following @Drew Baker's solution. 因此,我认为为AngularJS用户粘贴一个好主意,这是@Drew Baker解决方案之后的代码。
AngularJs way of the same code AngularJs的相同代码方式
1. Html : use the bellow tag in you html file: 1. HTML :在您的HTML文件中使用以下标签:
<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.用业力茉莉花进行单元测试 :
'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]);
});
});
If we have a greater number of such svg images we can also take the help of font-files. 如果我们有更多这样的svg图像,我们也可以借助字体文件。
Sites like https://glyphter.com/ can get us a font file from our svgs. https://glyphter.com/之类的网站可以从svgs中获取字体文件。
Eg 例如
@font-face {
font-family: 'iconFont';
src: url('iconFont.eot');
}
#target{
color: white;
font-size:96px;
font-family:iconFont;
}