svg之间还能互相影响?

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:项目就不上图了,总之其中存在各式各样的图标。最终选择了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返回的是一个包含 attributescontent 的对象,我们无法直接使用。处理后的结果如下代码所示:

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来控制各式各样图标的显示。

遇到的问题

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之间还能互相影响?

当我把第一个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之间还能互相影响?

至此,真相已经付出了水面。svg在寻找重用元素时的机制为:在当前HTML环境中寻找第一个匹配的元素。并不是我们想象中的在svg自己内部寻找或者逐层往外寻找。所以,在html中直接引入svg必然会存在互相影响的问题,也必然会带来一些未知的风险。那么到底有没有较为安全的方案呢?我觉得方法总比困难多,解决方案肯定是存在的。为了防止互相影响,我们可以采用使用css中的background-image属性将svg引入,该方案中的svg在寻找重用元素时,仅仅会寻找自身标签内是否存在,而不会向外寻找,因此一定程度上保证了svg图标的安全性。那么我们以后要一直使用该种方案吗?我觉得还是分场景使用最为合适。例如:一成不变的svg图标可以采用css的方式引入,带有交互行为的图标可以采用html的方式引入,方便修改样式。当然,我觉得最重要的就是,对于我们直接使用的图标,svg内最好干净的仅剩下path标签,这样不会带来任何问题。

同样,svg sprites使用use引入同样存在问题。。


以上所述就是小编给大家介绍的《svg之间还能互相影响?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Machine Learning

Machine Learning

Kevin Murphy / The MIT Press / 2012-9-18 / USD 90.00

Today's Web-enabled deluge of electronic data calls for automated methods of data analysis. Machine learning provides these, developing methods that can automatically detect patterns in data and then ......一起来看看 《Machine Learning》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换