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之间还能互相影响?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

软件随想录

软件随想录

Joel Spolsky / 阮一峰 / 人民邮电出版社 / 2009 / 49.00元

《软件随想录:程序员部落酋长Joel谈软件》是一部关于软件技术、人才、创业和企业管理的随想文集,作者以诙谐幽默的笔触将自己在软件行业的亲身感悟娓娓道来,观点新颖独特,内容简洁实用。全书分为 36讲,每一讲都是一个独立的专题。 《软件随想录:程序员部落酋长Joel谈软件》从不同侧面满足了软件开发人员、设计人员、管理人员及从事软件相关工作的人员的学习与工作需要。一起来看看 《软件随想录》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器