問題描述

將 SVG 輸出直接放置在頁面程式碼中我可以像 CSS 那樣簡單地修改填充顏色:

polygon.mystar {
    fill: blue;
}​

circle.mycircle {
    fill: green;
}

這是非常好的,但是我正在尋找一種方法來修改 SVG 的”fill” 屬性作為一個 BACKGROUND-IMAGE 。

html {
    background-image: url(../img/bg.svg);
}

現在如何改變顏色?甚至有可能嗎

作為參考,以下是我的外部 SVG 檔案的內容:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679
    118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>

最佳解決方案

我認為你這樣做的唯一方法是從一些伺服器端機制來服務你的 svg 。只需建立一個資源伺服器端,根據 GET 引數輸出您的 svg,並且您在某個 URL 上提供它。

那麼你只需要在你的 css 中使用這個 url 。

因為作為一個背景 img,它不是 DOM 的一部分,你不能操縱它。另一種可能性是定期使用它,以正常方式將其嵌入頁面,但絕對定位,使其全寬頁面的高度,然後使用 z-index css 屬性將其放在頁面上的所有其他 DOM 元素之後。

次佳解決方案

我需要類似的東西,並希望堅持使用 CSS 。我想出了一個完成這項工作的 LESS mixin 。不幸的是,它的瀏覽器支援有點鬆了一口氣。見下文。

.element-color(@color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="@{color}" ... /></g></svg>');
}

流行,混合到你的規則,更新顏色,whammo 。您也可以根據需要新增更多變數。

.element-color(#fff);

更新:如果您不使用前處理器 (LESS /SASS),則可以執行此操作。

// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');

Here is more info 將完整的 SVG 程式碼嵌入到您的 CSS 檔案中。它還提到瀏覽器相容性,這是一個有點太小,這是一個可行的選擇。

第三種解決方案

另一種方法是使用面膜。然後,您可以更改蒙版元素的背景顏色。這與更改 svg 的 fill 屬性具有相同的效果。

HTML:

<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>

CSS:

glyph {
    display: inline-block;
    width:  24px;
    height: 24px;
}

glyph.star {
  -webkit-mask: url(star.svg) no-repeat 100% 100%;
  mask: url(star.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: yellow;
}

glyph.heart {
  -webkit-mask: url(heart.svg) no-repeat 100% 100%;
  mask: url(heart.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: red;
}

你會在這裡找到一個完整的教程:http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images(不是我自己的) 。它提出了各種方法 (不限於掩模) 。

第四種方案

下載您的 svg 作為文字。

使用 javascript 修改您的 svg 文字以更改 paint /stroke /fill color [s] 。

然後按照 here 所述將修改後的 svg 字串嵌入到 css 中。

第五種方案

現在你可以在客戶端這樣做:

var green = '3CB54A';
var red = 'ED1F24';
var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"  width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";

Fiddle here!

第六種方案

有可能與 Sass!你唯一要做的就是 url-encode 你的 svg 程式碼。這可以在 Sass 中使用輔助功能。我為此做了一個代號。看這個:

http://codepen.io/philippkuehn/pen/zGEjxB

// choose a color

$icon-color: #F84830;


// functions to urlencode the svg string

@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}

@function url-encode($string) {
  $map: (
    "%": "%25",
    "<": "%3C",
    ">": "%3E",
    " ": "%20",
    "!": "%21",
    "*": "%2A",
    "'": "%27",
    '"': "%22",
    "(": "%28",
    ")": "%29",
    ";": "%3B",
    ":": "%3A",
    "@": "%40",
    "&": "%26",
    "=": "%3D",
    "+": "%2B",
    "$": "%24",
    ",": "%2C",
    "/": "%2F",
    "?": "%3F",
    "#": "%23",
    "[": "%5B",
    "]": "%5D"
  );
  $new: $string;
  @each $search, $replace in $map {
    $new: str-replace($new, $search, $replace);
  }
  @return $new;
}

@function inline-svg($string) {
  @return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}


// icon styles
// note the fill="' + $icon-color + '"

.icon {
  display: inline-block;
  width: 50px;
  height: 50px;
  background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
  c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
  c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}

第七種方案

您可以將 SVG 儲存在變數中。然後根據您的需要 (即設定寬度,高度,顏色等) 操作 SVG 字串。然後使用結果設定背景,例如

$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';

$icon-color: #f00;
$icon-color-hover: #00f;

@function str-replace($string, $search, $replace: '') {
    $index: str-index($string, $search);

    @if $index {
        @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
    }

    @return $string;
}

@function svg-fill ($svg, $color) {
  @return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}

@function svg-size ($svg, $width, $height) {
  $svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
  $svg: str-replace($svg, '<svg', '<svg height="#{$height}"');

  @return $svg;
}

.icon {
  $icon-svg: svg-size($circle-icon-svg, 20, 20);

  width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');

  &:hover {
    background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
  }
}

我也做了演示,http://sassmeister.com/gist/4cf0265c5d0143a9e734

該程式碼對 SVG 做了一些假設,例如<svg /> 元素不具有現有的填充顏色,並且不設定 width 或 height 屬性。由於輸入在 SCSS 檔案中是硬編碼的,所以執行這些約束是非常容易的。

不要擔心程式碼重複。 gzip 壓縮使差異可以忽略不計。

第八種方案

您可以為此建立自己的 SCSS 功能。將以下內容新增到 config.rb 檔案中。

require 'sass'
require 'cgi'

module Sass::Script::Functions

  def inline_svg_image(path, fill)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    svg.gsub! '{color}', fill.value
    encoded_svg = CGI::escape(svg).gsub('+', '%20')
    data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

那麼你可以在你的 CSS 中使用它:

.icon {
  background-image: inline-svg-image('icons/icon.svg', '#555');
}

您將需要編輯 SVG 檔案,並用 fill = “{color}” 替換標記中的任何填充屬性

圖示路徑始終與相同 config.rb 檔案中的 images_dir 引數相關。

類似於其他一些解決方案,但這是非常乾淨,保持您的 SCSS 檔案整潔!

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇