首頁 >科技週邊 >IT業界 >'可重新連接的SVG符號:如何製作它們(以及為什麼)

'可重新連接的SVG符號:如何製作它們(以及為什麼)

Jennifer Aniston
Jennifer Aniston原創
2025-02-18 10:17:09334瀏覽

SVG圖標在現代網頁設計中的應用日益廣泛,這得益於其可縮放性、小文件尺寸以及CSS樣式化能力,使其成為響應式網站的理想選擇。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

儘管SVG可以使用CSS進行樣式化,但這僅在SVG代碼嵌入HTML頁面時才有效。這意味著,除非SVG嵌入,否則無法修改SVG的單個部分。

本文介紹了“可換膚SVG符號”的概念,其中SVG圖像的“骨架”保持不變,但表面外觀可以輕鬆更改。

文章提出了一種解決無法修改SVG單個部分問題的方案。這涉及為SVG中的每個形狀創建一個符號,每個符號都在同一個viewBox中,允許根據需要對每個元素進行樣式設置。

作者詳細介紹了使用Adobe Illustrator和Gulp構建SVG符號的工作流程,並指出此方法與所有現代瀏覽器兼容。

SVG在現代網頁中的廣泛應用在2016年得到了顯著提升,這要歸功於其文件大小、可縮放性和CSS樣式化能力。

它可用於圖標系統(參見《構建您自己的SVG圖標》),儘管在某些情況下,圖標字體可能更可取(參見《圖標大戰:字體與SVG》)。

但SVG也可用於徽標或圖形元素(至少不是過於復雜的元素),其天然的靈活性使其成為響應式網站的完美解決方案(參見Sara Soueidan的《使用CSS製作響應式SVG》) 。

使用SVG可以利用CSS來定位和更改整個元素的大小和顏色,但是,除非您的SVG代碼嵌入到HTML頁面中,否則無法通過這種方式修改其單個部分。

問題

讓我們來看一個更簡單的例子。這裡有一個圖像,我們需要以多種顏色顯示它。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

傳統上,我們會創建三個獨立的圖像——每個圖像都有不同的“風格”。但是,如果我們想使用單個SVG文件並在渲染時對其進行樣式設置呢?

此外,有沒有辦法將我們的圖像製作成“SVG符號”以利用瀏覽器緩存?

我將其稱為“可換膚SVG符號”——SVG圖像的“骨架”保持不變,但表面外觀很容易改變。

理想的解決方案是通過CSS選擇器訪問符號元素並向其添加一些規則(與嵌入式SVG使用的方法相同)。

在下面的示例中,我已經向每個三角形添加了一個類(頂部、右側、底部和左側),將圖像排列為符號,並嘗試通過CSS修改它,方法如下:

<code class="language-css">.top { fill: #356BA5; }
.right { fill: #357FD9; }
/* and so on... */</code>

不幸的是,目前這僅適用於Firefox,如下面的CodePen演示所示。只有在Firefox上,第二個圖像才會顯示為藍色色調(為方便起見,我在筆中嵌入了符號代碼,但使用外部SVG文件也會得到相同的結果)。

CodePen鏈接1

CodePen鏈接2

在大型項目中,我們可能有許多這樣的元素,維護問題是一個重要因素,因此我一直在尋找一種更好地組織項目資源的方法。

我的目標是純粹的CSS解決方案:之前的示例可以使用單個三角形SVG來重寫,可以通過CSS進行旋轉、移動和著色。

但我並不喜歡這個解決方案:在我看來,它只是轉移了問題,並沒有解決問題。有多少現實世界的徽標的組件具有相同的形狀?

Sara Soueidan比我更好地解釋了這個問題,並為我們提供了一個使用CSS變量的巧妙解決方案。不幸的是,CSS變量仍然是一項實驗性技術,Microsoft瀏覽器不支持它們。

解決方案

正如經常發生的那樣,解決方案是如此簡單,以至於你會因為之前沒有想到而感到愚蠢。

幾個月前,我看到新的Medium徽標時發現了它(似乎Medium已經更改了他們的徽標代碼——你必須相信我的話)。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

您可以看到Medium徽標由四個“形狀”組成,每個形狀都填充了不同的純色。黑白版本與綠色版本相同(當然,顏色除外)。

同時擁有這兩個版本的單個文件的解決方案是為每個形狀簡單地構建一個符號,每個符號都在同一個viewBox中。

讓我們將其應用於我們的示例,並為圖像中的每個形狀創建一個符號。它們都共享整個圖像的相同viewBox(0 0 54 54),因此它們無需任何其他指令即可定位在正確的位置。只需注意避免在符號代碼中使用fill、stroke、style等屬性)。

<code class="language-xml"><svg xmlns="https://www.w3.org/2000/svg">
    <symbol id="top" viewbox="0 0 54 54">
        <polygon points="54 0 0 0 27 27 54 0"></polygon>
    </symbol>
    <symbol id="right" viewbox="0 0 54 54">
        <polygon points="54 54 54 0 27 27 54 54"></polygon>
    </symbol>
    <symbol id="bottom" viewbox="0 0 54 54">
        <polygon points="0 54 54 54 27 27 0 54"></polygon>
    </symbol>
    <symbol id="left" viewbox="0 0 54 54">
        <polygon points="0 0 0 54 27 27 0 0"></polygon>
    </symbol>
</svg></code>

現在我們可以將它們組合到單個SVG容器中:

<code class="language-xml"><svg>
    <use class="top" xlink:href="#top"></use>
    <use class="right" xlink:href="#right"></use>
    <use class="bottom" xlink:href="#bottom"></use>
    <use class="left" xlink:href="#left"></use>
</svg></code>

每個use元素都可以根據需要進行樣式設置,最重要的是,它與所有現代瀏覽器兼容:

CodePen鏈接3

就是這樣。

我們只需要這樣排列我們的SVG文件。當然,我們可以手動完成,但是如果您必須管理許多圖形元素,或者需要在更多項目中快速編輯和重用它們,則需要更智能、更快速的工作流程。我已經找到了使用Adobe Illustrator和一些Gulp的解決方案。

SVG符號構建工作流程

此技術的原理與我在《構建您自己的SVG圖標》和《使用Illustrator和IcoMoon創建圖標字體》文章中介紹的相同,因此請查看它們以了解第一步。

假設我們有兩個元素,就像下面的圖像一樣。每個元素都排列在一個特定的畫板中:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

為方便起見,我們為它們添加了一些顏色,儘管我們知道填充顏色(以及如果有的話,描邊顏色、描邊大小等)將通過CSS進行編輯。

由於每個符號必須有其畫板,因此我們現在必須將每個圖像分割成與每個彩色部分一樣多的畫板。

這可以在Illustrator中非常快速地完成,剪切每個元素,選擇目標畫板並選擇“粘貼到位”命令。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

請注意,每個畫板都有一個特定的名稱:它將用於符號ID。

現在我們可以使用全新的“文件→導出→導出為屏幕”命令將我們的畫板導出為SVG。

這是最新Illustrator版本的真正有用的新工具:它允許您使用單個命令以多種格式保存每個畫板或用戶定義的資源。

從導出面板中選擇“畫板”,將“SVG”設置為輸出格式,然後選擇目標文件夾:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

每個畫板都將導出為單個SVG文件:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

現在我們需要將所有文件組合成SVG符號,並刪除一些不需要的SVG屬性:一個小型的gulp腳本將幫助我們快速完成此操作。

Gulp的使用

下一節內容略微技術性一些,但是——如果您願意——它將為您提供一種快速、簡潔的方法來生成這樣的多功能SVG。

我已經在SitePoint上寫過關於Gulp的文章,您也可以在網上找到大量關於Gulp安裝和所有相關參數的資源,因此我假設您已經安裝了它,並且您知道我們在談論什麼。

無論如何,如果您不喜歡Gulp,您也可以手動完成以下所有步驟。在開始使用Gulp之前,我已經多次這樣做過:這絕對是一種學習的好方法,在小型項目或不需要持續編輯和維護工作的地方已經足夠了。

因此,我們有一些SVG文件,每個文件都像下面的示例一樣排列(d屬性已縮短,以方便起見):

<code class="language-css">.top { fill: #356BA5; }
.right { fill: #357FD9; }
/* and so on... */</code>

我們的目標是將所有圖像排列為單個文件中的SVG符號,同時去除所有不需要的屬性:

<code class="language-xml"><svg xmlns="https://www.w3.org/2000/svg">
    <symbol id="top" viewbox="0 0 54 54">
        <polygon points="54 0 0 0 27 27 54 0"></polygon>
    </symbol>
    <symbol id="right" viewbox="0 0 54 54">
        <polygon points="54 54 54 0 27 27 54 54"></polygon>
    </symbol>
    <symbol id="bottom" viewbox="0 0 54 54">
        <polygon points="0 54 54 54 27 27 0 54"></polygon>
    </symbol>
    <symbol id="left" viewbox="0 0 54 54">
        <polygon points="0 0 0 54 27 27 0 0"></polygon>
    </symbol>
</svg></code>

除了Gulp之外,我們的工作還需要一些其他擴展:

  • 首先,gulp-svgstore和gulp-svgmin用於組合和壓縮我們的svg文件
  • gulp-rename用於調整id名稱並為我們的目標文件指定名稱。如果您想使用之前的Illustrator SVG導出命令,則尤其需要此模塊,我們稍後將介紹它。

現在我們可以安排我們的Gulpfile(代碼也可以作為公共Gist獲得):

<code class="language-xml"><svg>
    <use class="top" xlink:href="#top"></use>
    <use class="right" xlink:href="#right"></use>
    <use class="bottom" xlink:href="#bottom"></use>
    <use class="left" xlink:href="#left"></use>
</svg></code>

加載模塊後,我們指示要解析的文件(svg_files/*.svg)。

SVGstore使用每個文件的名稱來設置符號id屬性(即,名為umbrella.svg的文件將成為具有id="umbrella"的符號)。如果您使用新的Illustrator“導出為屏幕”面板,則可以避免第一個rename命令,因為您的文件將與它們所屬的畫板完全相同命名。

但是舊版本的Illustrator通過將Illustrator文件名與畫板名稱連接起來創建文件名,因此我們需要重命名文件以刪除Illustrator文件名前綴:

<code class="language-xml"><svg id="Layer_1" data-name="Layer 1" xmlns="https://www.w3.org/2000/svg" width="54" height="54" viewbox="0 0 54 54">
<title>umbrella-handle</title>
<path d="..." fill="#603813"></path>
</svg></code>

現在我們可以清理我們的文件了。 gulp-svgmin是SVGO的Gulp版本,“基於Nodejs的工具,用於優化SVG矢量圖形文件”(Jake Archibald發布了一個SVGO的在線版本,如果您想手動排列文件,這非常有用)。

SVGO有很多可配置的選項(您可以在項目頁面中瀏覽所有選項),但我們只需要幾個(當然,您可以根據需要自定義腳本):

  • cleanupIDs:從文件中刪除所有id
  • removeDoctype、removeComments和removeStyleElement:去除所有文檔類型聲明、註釋和<style></style>元素
  • removeDimensions:如果存在viewBox,則刪除所有width和height屬性
  • cleanupNumericValues:將數值四捨五入到合理的精度級別
  • removeAttrs:刪除所有指定的屬性

接下來,將文件傳遞給svgstore以組合到一個唯一文件中,然後重命名並保存。

使用幾次後,您應該能夠在幾分鐘內為每個項目安排它,並且它將使您能夠在需要時快速重建您的SVG符號文件。

這是一個結果示例(即使在這個筆中,我也為了方便而嵌入了svg文件,但您可以安全地將其鏈接為外部文件):

CodePen鏈接4

是否有任何警告?

由於此方法基於樣式化use元素,因此當polyfill(例如svg4everybody)刪除它們時,我們會遇到問題。

在不支持外部符號鏈接的瀏覽器(所有IE)中,svg4everybody會用匹配符號的內容替換所有use元素。因此,應用於use的所有css規則都不會生效。

這可以通過調整CSS選擇器以適應內部符號元素(path、circle等)來解決,但這可能有點棘手。

額外獎勵

此工作流程有無限種變體:您可以處理描邊、文本等。

另一個值得探索的有趣功能是使用Illustrator符號:它們導出為SVG符號,這帶來了許多可能性。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

感謝您的閱讀。

關於可換膚SVG符號的常見問題

使用SVG符號而不是其他圖像格式進行網頁設計的優勢是什麼?

與JPEG、PNG或GIF等其他圖像格式相比,SVG符號具有多種優勢。首先,SVG是可縮放矢量圖形,這意味著它們可以重新調整大小而不會損失質量。這對於響應式網頁設計特別有用,在響應式網頁設計中,需要在不同設備上以不同大小顯示相同的圖像。其次,SVG符號可以使用CSS進行樣式化,從而提高設計靈活性。最後,SVG的文件大小通常小於其位圖對應物,這可以加快加載速度並提高網站性能。

如何修改SVG符號的顏色?

您可以使用CSS修改SVG符號的顏色。默認情況下,SVG繼承其父元素的顏色。但是,您可以通過在CSS中定位SVG或其子元素並應用所需顏色來覆蓋此設置。例如,您可以使用fill屬性更改SVG內部的顏色,或使用stroke屬性更改其輪廓的顏色。

我可以在所有網頁瀏覽器中使用SVG符號嗎?

SVG符號在所有現代網頁瀏覽器(包括Chrome、Firefox、Safari和Edge)中得到廣泛支持。但是,舊版本的Internet Explorer(IE8及以下版本)不支持SVG。如果您需要支持這些舊瀏覽器,則可能需要提供PNG或JPEG圖像作為後備。

如何動畫化SVG符號?

可以使用CSS動畫或JavaScript動畫化SVG符號。 CSS動畫更簡單且性能更高,但JavaScript提供更多控制和靈活性。您可以動畫化SVG的各種屬性,例如其位置、大小、旋轉、顏色和不透明度。

我可以在HTML中使用SVG符號嗎?

是的,SVG符號可以直接嵌入到HTML中。這可以使用<svg></svg><symbol></symbol>標籤來完成。 <symbol></symbol>標籤用於定義SVG符號,<use></use>標籤用於實例化它。這允許您一次定義SVG符號,並在整個HTML中多次重用它。

如何使我的SVG符號更易訪問?

要使您的SVG符號更易訪問,您應該使用SVG中的<title></title><desc></desc>標籤提供替代文本。 <title></title>標籤為SVG提供簡短的描述性標題,<desc></desc>標籤提供更長的描述。這些標籤由屏幕閱讀器讀取,並為視力障礙用戶提供重要的上下文。

我可以在CSS中使用SVG符號嗎?

是的,SVG符號可以用作CSS中的背景圖像。這可以通過將SVG編碼為數據URL並將其用作background-image屬性的值來完成。但是,此方法不允許您使用CSS設置SVG的樣式或對其進行動畫處理。

如何優化我的SVG符號以提高性能?

有幾種方法可以優化您的SVG符號以提高性能。首先,您可以壓縮SVG代碼以減小其文件大小。其次,您可以使用gzip壓縮進一步減小文件大小。最後,您可以使用HTTP/2來服務您的SVG,這允許更快、更高效的數據傳輸。

我可以在JavaScript中使用SVG符號嗎?

是的,SVG符號可以用JavaScript進行操作。這允許您動態更改SVG的屬性,例如其顏色、大小、位置和可見性。您還可以使用JavaScript來動畫化SVG、創建交互式SVG和動態加載SVG。

如何創建響應式SVG符號?

要創建響應式SVG符號,您應該為SVG的寬度和高度使用相對單位(如百分比),而不是絕對單位(如像素)。這允許SVG與其父元素一起縮放。您還可以使用viewBox屬性指定SVG的縱橫比和坐標系,這允許它按比例縮放。

以上是'可重新連接的SVG符號:如何製作它們(以及為什麼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn