最近搞了一个项目,基于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引入一样存在问题。。