最近搞了一個項目,基於React,用了本身的腳手架fdt。css
項目就不上圖了,總之其中存在各式各樣的圖標。最終選擇了svg來控制圖標的顯示,緣由主要有以下幾方面:html
svg的使用方式多種多樣,適合本身的纔是最好的。下面簡單介紹下咱們的項目如何在fdt腳手架中使用了svg。由於fdt基於webpack打包,因此webpack中必不可少須要增長針對svg的配置。代碼以下:react
// webpack.config.js
{
test: /\.svg$/,
use: [
{
loader: path.resolve(__dirname, "./fdtsvgloader")
},
"svg-loader"
],
include: [path.resolve(opts.baseDir, "src")],
exclude: [path.resolve(opts.baseDir, "src/svginline")]
}
複製代碼
咱們依然使用svg-loader進行svg的處理,可是svg-loader返回的是一個包含attributes
和content
的對象,咱們沒法直接使用。處理後的結果以下代碼所示:webpack
module.exports = {
attributes: {
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 1024 1024'
},
content: '<path d="M441.9 167.3l-19.8-19.8c-4.7-4.7-12.3-4.7-17 0L224 328.2 42.9 147.5c-4.7-4.7-12.3-4.7-17 0L6.1 167.3c-4.7 4.7-4.7 12.3 0 17l209.4 209.4c4.7 4.7 12.3 4.7 17 0l209.4-209.4c4.7-4.7 4.7-12.3 0-17z"/>'
}
複製代碼
所以,咱們在fdt中單獨寫了一個loader來獲得咱們想要的svg格式。代碼以下:web
// fdtsvgloader.js
module.exports = function(source) {
return `
${source}
var fdtsvg = require('fdt-svg-loader')
module.exports = fdtsvg(module.exports)
`;
};
// fdt-svg-loader
var React = require("react");
module.exports = function(svg) {
const content = svg.content;
return function(props) {
const newprops = { viewBox: "0 0 1024 1024", height: "20px", fill: "#000" };
newprops.dangerouslySetInnerHTML = { __html: content };
newprops;
return React.createElement("svg", { ...newprops, ...props });
};
};
複製代碼
其中,fdtsvgloader.js中接受的參數即爲svg-loader處理後的結果。最後,通過fdt-svg-loader處理後,獲得了React建立的svg元素,幷包含默認屬性viewBox,height以及fill值。所以咱們在組件中能夠以下方式引用svg:瀏覽器
// demo.tsx
import PptIcon from "@/image/newppt.svg";
export default class Demo extends Component {
render() {
return <PptIcon width="18" height="18" viewBox="0 0 27 34" />;
}
}
複製代碼
demo中傳遞的屬性即可覆蓋默認屬性,靈活控制svg的大小。至此,咱們在項目中愉快的使用svg來控制各式各樣圖標的顯示。安全
<g>
該標籤表明組合<defs>
定義重用圖形<polygon>
定義多邊形<mask>
定義蒙層<use>
實現SVG現有圖形的重用既然沒法直接找到答案,那隻好上排除法來尋找問題所在了。最後發現,問題出現的緣由是咱們新引入的圖標影響了原有圖標。svg互相影響也真的讓我很是震驚。 那究竟是怎麼互相影響的呢?緣由就是新的圖標中定義了一個mask蒙層,屬性id爲mask-2
。受影響的圖標中,path標籤的mask屬性引用了該mask-2
的蒙層,致使新圖標的出現影響了部分舊圖標。 那麼對於直接在html中引入svg,瀏覽器對於重用圖標的尋找機制是怎麼樣的呢?咱們作了以下測試:bash
<svg width="400" height="300">
<defs>
<linearGradient id='white2black'>
<stop offset="0" stop-color="white"></stop>
<stop offset="100%" stop-color="black"></stop>
</linearGradient>
<mask id="opacity">
<rect x="0" y="0" width="400" height="300" fill="url(#white2black)"></rect>
</mask>
</defs>
<rect id="back" x="0" y="0" width="400" height="300" fill="#d4fcff"></rect>
<rect id="front" x="0" y="0" width="400" height="300" fill="#fcd3db" mask="url(#opacity)"></rect>
</svg>
<svg width="600" height="300">
<defs>
<linearGradient id='white2black'>
<stop offset="0" stop-color="blue"></stop>
<stop offset="50%" stop-color="black"></stop>
<stop offset="100%" stop-color="green"></stop>
</linearGradient>
<mask id="opacity">
<rect x="50" y="0" width="600" height="400" fill="green"></rect>
</mask>
</defs>
<rect id="back" x="0" y="0" width="400" height="300" fill="#d4fcff"></rect>
<rect id="front" x="0" y="0" width="400" height="300" fill="#fcd3db" mask="url(#opacity)"></rect>
</svg>
複製代碼
該代碼的展現效果爲: svg
<svg width="400" height="300">
<defs>
<linearGradient id='white2black'>
<stop offset="0" stop-color="white"></stop>
<stop offset="100%" stop-color="black"></stop>
</linearGradient>
</defs>
<rect id="back" x="0" y="0" width="400" height="300" fill="#d4fcff"></rect>
<rect id="front" x="0" y="0" width="400" height="300" fill="#fcd3db" mask="url(#opacity)"></rect>
</svg>
<svg width="600" height="300">
<defs>
<linearGradient id='white2black'>
<stop offset="0" stop-color="blue"></stop>
<stop offset="50%" stop-color="black"></stop>
<stop offset="100%" stop-color="green"></stop>
</linearGradient>
<mask id="opacity">
<rect x="50" y="0" width="600" height="400" fill="green"></rect>
</mask>
</defs>
<rect id="back" x="0" y="0" width="400" height="300" fill="#d4fcff"></rect>
<rect id="front" x="0" y="0" width="400" height="300" fill="#fcd3db" mask="url(#opacity)"></rect>
</svg>
複製代碼
效果變爲: 測試
一樣,svg sprites使用use引入一樣存在問題。。