内容简介:项目就不上图了,总之其中存在各式各样的图标。最终选择了svg来控制图标的显示,原因主要有如下几方面:svg的使用方式多种多样,适合自己的才是最好的。下面简单介绍下我们的项目如何在fdt脚手架中使用了svg。因为fdt基于webpack打包,所以webpack中必不可少需要增加针对svg的配置。代码如下:我们依然使用svg-loader进行svg的处理,但是svg-loader返回的是一个包含
项目就不上图了,总之其中存在各式各样的图标。最终选择了svg来控制图标的显示,原因主要有如下几方面:
- 相比传统的图片,尺寸更小,可压缩性更强
- 可伸缩,更清晰
- 方便读取和修改
- 设计软件直接导出
svg的使用方式多种多样,适合自己的才是最好的。下面简单介绍下我们的项目如何在fdt脚手架中使用了svg。因为fdt基于webpack打包,所以webpack中必不可少需要增加针对svg的配置。代码如下:
// 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
的对象,我们无法直接使用。处理后的结果如下代码所示:
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格式。代码如下:
// 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来控制各式各样图标的显示。
遇到的问题
但是突然有一天,在一个慵懒的午后,我们的测试同学突然告诉我,页面中的图标从左边变成了右边的样子。短暂的惊慌之后,我迅速抄起键盘寻找bug的所在之处。 实不相瞒,在做此项目之前,我较少涉猎svg的知识,对于svg我本身并不是很熟悉。因此,寻找bug的过程中遇到了一些困难和挫折。在较短的时间内并没有迅速找到问题所在,因此我首先想到的是重新更换一下图标(设计软件中导出的图标我们做过手动处理)。我惊奇的发现,这个方法居然好用,果断完成上线。 事后慢慢琢磨这个事情,一个svg图片并没有受到外部CSS的影响,为什么会突然导致问题呢?为了更快的发现问题,我仔细研究了一下我们的svg图标的结构,学到了一些关于svg的内容:
<g> <defs> <polygon> <mask> <use>
既然无法直接找到答案,那只好上排除法来寻找问题所在了。最后发现,问题出现的原因是我们新引入的图标影响了原有图标。svg互相影响也真的让我非常震惊。 那到底是怎么互相影响的呢?原因就是新的图标中定义了一个mask蒙层,属性id为 mask-2
。受影响的图标中,path标签的mask属性引用了该 mask-2
的蒙层,导致新图标的出现影响了部分旧图标。 那么对于直接在html中引入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> <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的mask标签删除之后
<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在寻找重用元素时的机制为:在当前HTML环境中寻找第一个匹配的元素。并不是我们想象中的在svg自己内部寻找或者逐层往外寻找。所以,在html中直接引入svg必然会存在互相影响的问题,也必然会带来一些未知的风险。那么到底有没有较为安全的方案呢?我觉得方法总比困难多,解决方案肯定是存在的。为了防止互相影响,我们可以采用使用css中的background-image属性将svg引入,该方案中的svg在寻找重用元素时,仅仅会寻找自身标签内是否存在,而不会向外寻找,因此一定程度上保证了svg图标的安全性。那么我们以后要一直使用该种方案吗?我觉得还是分场景使用最为合适。例如:一成不变的svg图标可以采用css的方式引入,带有交互行为的图标可以采用html的方式引入,方便修改样式。当然,我觉得最重要的就是,对于我们直接使用的图标,svg内最好干净的仅剩下path标签,这样不会带来任何问题。
同样,svg sprites使用use引入同样存在问题。。
以上所述就是小编给大家介绍的《svg之间还能互相影响?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。