首页 > 科技周边 > IT业界 > '可重新连接的SVG符号:如何制作它们(以及为什么)

'可重新连接的SVG符号:如何制作它们(以及为什么)

Jennifer Aniston
发布: 2025-02-18 10:17:09
原创
313 人浏览过

SVG图标在现代网页设计中的应用日益广泛,这得益于其可缩放性、小文件尺寸以及CSS样式化能力,使其成为响应式网站的理想选择。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

尽管SVG可以使用CSS进行样式化,但这仅在SVG代码嵌入HTML页面时才有效。这意味着,除非SVG嵌入,否则无法修改SVG的单个部分。

本文介绍了“可换肤SVG符号”的概念,其中SVG图像的“骨架”保持不变,但表面外观可以轻松更改。

文章提出了一种解决无法修改SVG单个部分问题的方案。这涉及为SVG中的每个形状创建一个符号,每个符号都在同一个viewBox中,允许根据需要对每个元素进行样式设置。

作者详细介绍了使用Adobe Illustrator和Gulp构建SVG符号的工作流程,并指出此方法与所有现代浏览器兼容。

SVG在现代网页中的广泛应用在2016年得到了显着提升,这要归功于其文件大小、可缩放性和CSS样式化能力。

它可用于图标系统(参见《构建您自己的SVG图标》),尽管在某些情况下,图标字体可能更可取(参见《图标大战:字体与SVG》)。

但SVG也可用于徽标或图形元素(至少不是过于复杂的元素),其天然的灵活性使其成为响应式网站的完美解决方案(参见Sara Soueidan的《使用CSS制作响应式SVG》) 。

使用SVG可以利用CSS来定位和更改整个元素的大小和颜色,但是,除非您的SVG代码嵌入到HTML页面中,否则无法通过这种方式修改其单个部分。

问题

让我们来看一个更简单的例子。这里有一个图像,我们需要以多种颜色显示它。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

传统上,我们会创建三个独立的图像——每个图像都有不同的“风格”。但是,如果我们想使用单个SVG文件并在渲染时对其进行样式设置呢?

此外,有没有办法将我们的图像制作成“SVG符号”以利用浏览器缓存?

我将其称为“可换肤SVG符号”——SVG图像的“骨架”保持不变,但表面外观很容易改变。

理想的解决方案是通过CSS选择器访问符号元素并向其添加一些规则(与嵌入式SVG使用的方法相同)。

在下面的示例中,我已经向每个三角形添加了一个类(顶部、右侧、底部和左侧),将图像排列为符号,并尝试通过CSS修改它,方法如下:

.top { fill: #356BA5; }
.right { fill: #357FD9; }
/* and so on... */
登录后复制
登录后复制

不幸的是,目前这仅适用于Firefox,如下面的CodePen演示所示。只有在Firefox上,第二个图像才会显示为蓝色色调(为方便起见,我在笔中嵌入了符号代码,但使用外部SVG文件也会得到相同的结果)。

CodePen链接1

CodePen链接2

在大型项目中,我们可能有许多这样的元素,维护问题是一个重要因素,因此我一直在寻找一种更好地组织项目资源的方法。

我的目标是纯粹的CSS解决方案:之前的示例可以使用单个三角形SVG来重写,可以通过CSS进行旋转、移动和着色。

但我并不喜欢这个解决方案:在我看来,它只是转移了问题,并没有解决问题。有多少现实世界的徽标的组件具有相同的形状?

Sara Soueidan比我更好地解释了这个问题,并为我们提供了一个使用CSS变量的巧妙解决方案。不幸的是,CSS变量仍然是一项实验性技术,Microsoft浏览器不支持它们。

解决方案

正如经常发生的那样,解决方案是如此简单,以至于你会因为之前没有想到而感到愚蠢。

几个月前,我看到新的Medium徽标时发现了它(似乎Medium已经更改了他们的徽标代码——你必须相信我的话)。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

您可以看到Medium徽标由四个“形状”组成,每个形状都填充了不同的纯色。黑白版本与绿色版本相同(当然,颜色除外)。

同时拥有这两个版本的单个文件的解决方案是为每个形状简单地构建一个符号,每个符号都在同一个viewBox中。

让我们将其应用于我们的示例,并为图像中的每个形状创建一个符号。它们都共享整个图像的相同viewBox(0 0 54 54),因此它们无需任何其他指令即可定位在正确的位置。只需注意避免在符号代码中使用fill、stroke、style等属性)。

<svg xmlns="https://www.w3.org/2000/svg">
    <symbol id="top" viewBox="0 0 54 54">
        <polygon points="54 0 0 0 27 27 54 0"></polygon>
    </symbol>
    <symbol id="right" viewBox="0 0 54 54">
        <polygon points="54 54 54 0 27 27 54 54"></polygon>
    </symbol>
    <symbol id="bottom" viewBox="0 0 54 54">
        <polygon points="0 54 54 54 27 27 0 54"></polygon>
    </symbol>
    <symbol id="left" viewBox="0 0 54 54">
        <polygon points="0 0 0 54 27 27 0 0"></polygon>
    </symbol>
</svg>
登录后复制
登录后复制

现在我们可以将它们组合到单个SVG容器中:

<svg>
    <use class="top" xlink:href="#top"></use>
    <use class="right" xlink:href="#right"></use>
    <use class="bottom" xlink:href="#bottom"></use>
    <use class="left" xlink:href="#left"></use>
</svg>
登录后复制
登录后复制

每个use元素都可以根据需要进行样式设置,最重要的是,它与所有现代浏览器兼容:

CodePen链接3

就是这样。

我们只需要这样排列我们的SVG文件。当然,我们可以手动完成,但是如果您必须管理许多图形元素,或者需要在更多项目中快速编辑和重用它们,则需要更智能、更快速的工作流程。我已经找到了使用Adobe Illustrator和一些Gulp的解决方案。

SVG符号构建工作流程

此技术的原理与我在《构建您自己的SVG图标》和《使用Illustrator和IcoMoon创建图标字体》文章中介绍的相同,因此请查看它们以了解第一步。

假设我们有两个元素,就像下面的图像一样。每个元素都排列在一个特定的画板中:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

为方便起见,我们为它们添加了一些颜色,尽管我们知道填充颜色(以及如果有的话,描边颜色、描边大小等)将通过CSS进行编辑。

由于每个符号必须有其画板,因此我们现在必须将每个图像分割成与每个彩色部分一样多的画板。

这可以在Illustrator中非常快速地完成,剪切每个元素,选择目标画板并选择“粘贴到位”命令。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

请注意,每个画板都有一个特定的名称:它将用于符号ID。

现在我们可以使用全新的“文件→导出→导出为屏幕”命令将我们的画板导出为SVG。

这是最新Illustrator版本的真正有用的新工具:它允许您使用单个命令以多种格式保存每个画板或用户定义的资源。

从导出面板中选择“画板”,将“SVG”设置为输出格式,然后选择目标文件夹:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

每个画板都将导出为单个SVG文件:

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

现在我们需要将所有文件组合成SVG符号,并删除一些不需要的SVG属性:一个小型的gulp脚本将帮助我们快速完成此操作。

Gulp的使用

下一节内容略微技术性一些,但是——如果您愿意——它将为您提供一种快速、简洁的方法来生成这样的多功能SVG。

我已经在SitePoint上写过关于Gulp的文章,您也可以在网上找到大量关于Gulp安装和所有相关参数的资源,因此我假设您已经安装了它,并且您知道我们在谈论什么。

无论如何,如果您不喜欢Gulp,您也可以手动完成以下所有步骤。在开始使用Gulp之前,我已经多次这样做过:这绝对是一种学习的好方法,在小型项目或不需要持续编辑和维护工作的地方已经足够了。

因此,我们有一些SVG文件,每个文件都像下面的示例一样排列(d属性已缩短,以方便起见):

.top { fill: #356BA5; }
.right { fill: #357FD9; }
/* and so on... */
登录后复制
登录后复制

我们的目标是将所有图像排列为单个文件中的SVG符号,同时去除所有不需要的属性:

<svg xmlns="https://www.w3.org/2000/svg">
    <symbol id="top" viewBox="0 0 54 54">
        <polygon points="54 0 0 0 27 27 54 0"></polygon>
    </symbol>
    <symbol id="right" viewBox="0 0 54 54">
        <polygon points="54 54 54 0 27 27 54 54"></polygon>
    </symbol>
    <symbol id="bottom" viewBox="0 0 54 54">
        <polygon points="0 54 54 54 27 27 0 54"></polygon>
    </symbol>
    <symbol id="left" viewBox="0 0 54 54">
        <polygon points="0 0 0 54 27 27 0 0"></polygon>
    </symbol>
</svg>
登录后复制
登录后复制

除了Gulp之外,我们的工作还需要一些其他扩展:

  • 首先,gulp-svgstore和gulp-svgmin用于组合和压缩我们的svg文件
  • gulp-rename用于调整id名称并为我们的目标文件指定名称。如果您想使用之前的Illustrator SVG导出命令,则尤其需要此模块,我们稍后将介绍它。

现在我们可以安排我们的Gulpfile(代码也可以作为公共Gist获得):

<svg>
    <use class="top" xlink:href="#top"></use>
    <use class="right" xlink:href="#right"></use>
    <use class="bottom" xlink:href="#bottom"></use>
    <use class="left" xlink:href="#left"></use>
</svg>
登录后复制
登录后复制

加载模块后,我们指示要解析的文件(svg_files/*.svg)。

SVGstore使用每个文件的名称来设置符号id属性(即,名为umbrella.svg的文件将成为具有id="umbrella"的符号)。如果您使用新的Illustrator“导出为屏幕”面板,则可以避免第一个rename命令,因为您的文件将与它们所属的画板完全相同命名。

但是旧版本的Illustrator通过将Illustrator文件名与画板名称连接起来创建文件名,因此我们需要重命名文件以删除Illustrator文件名前缀:

<svg id="Layer_1" data-name="Layer 1" xmlns="https://www.w3.org/2000/svg" width="54" height="54" viewBox="0 0 54 54">
<title>umbrella-handle</title>
<path d="..." fill="#603813"></path>
</svg>
登录后复制

现在我们可以清理我们的文件了。gulp-svgmin是SVGO的Gulp版本,“基于Nodejs的工具,用于优化SVG矢量图形文件”(Jake Archibald发布了一个SVGO的在线版本,如果您想手动排列文件,这非常有用)。

SVGO有很多可配置的选项(您可以在项目页面中浏览所有选项),但我们只需要几个(当然,您可以根据需要自定义脚本):

  • cleanupIDs:从文件中删除所有id
  • removeDoctype、removeComments和removeStyleElement:去除所有文档类型声明、注释和<style></style>元素
  • removeDimensions:如果存在viewBox,则删除所有width和height属性
  • cleanupNumericValues:将数值四舍五入到合理的精度级别
  • removeAttrs:删除所有指定的属性

接下来,将文件传递给svgstore以组合到一个唯一文件中,然后重命名并保存。

使用几次后,您应该能够在几分钟内为每个项目安排它,并且它将使您能够在需要时快速重建您的SVG符号文件。

这是一个结果示例(即使在这个笔中,我也为了方便而嵌入了svg文件,但您可以安全地将其链接为外部文件):

CodePen链接4

是否有任何警告?

由于此方法基于样式化use元素,因此当polyfill(例如svg4everybody)删除它们时,我们会遇到问题。

在不支持外部符号链接的浏览器(所有IE)中,svg4everybody会用匹配符号的内容替换所有use元素。因此,应用于use的所有css规则都不会生效。

这可以通过调整CSS选择器以适应内部符号元素(path、circle等)来解决,但这可能有点棘手。

额外奖励

此工作流程有无限种变体:您可以处理描边、文本等。

另一个值得探索的有趣功能是使用Illustrator符号:它们导出为SVG符号,这带来了许多可能性。

‘Reskinnable’ SVG Symbols: How to Make Them (..and Why)

感谢您的阅读。

关于可换肤SVG符号的常见问题

使用SVG符号而不是其他图像格式进行网页设计的优势是什么?

与JPEG、PNG或GIF等其他图像格式相比,SVG符号具有多种优势。首先,SVG是可缩放矢量图形,这意味着它们可以重新调整大小而不会损失质量。这对于响应式网页设计特别有用,在响应式网页设计中,需要在不同设备上以不同大小显示相同的图像。其次,SVG符号可以使用CSS进行样式化,从而提高设计灵活性。最后,SVG的文件大小通常小于其位图对应物,这可以加快加载速度并提高网站性能。

如何修改SVG符号的颜色?

您可以使用CSS修改SVG符号的颜色。默认情况下,SVG继承其父元素的颜色。但是,您可以通过在CSS中定位SVG或其子元素并应用所需颜色来覆盖此设置。例如,您可以使用fill属性更改SVG内部的颜色,或使用stroke属性更改其轮廓的颜色。

我可以在所有网页浏览器中使用SVG符号吗?

SVG符号在所有现代网页浏览器(包括Chrome、Firefox、Safari和Edge)中得到广泛支持。但是,旧版本的Internet Explorer(IE8及以下版本)不支持SVG。如果您需要支持这些旧浏览器,则可能需要提供PNG或JPEG图像作为后备。

如何动画化SVG符号?

可以使用CSS动画或JavaScript动画化SVG符号。CSS动画更简单且性能更高,但JavaScript提供更多控制和灵活性。您可以动画化SVG的各种属性,例如其位置、大小、旋转、颜色和不透明度。

我可以在HTML中使用SVG符号吗?

是的,SVG符号可以直接嵌入到HTML中。这可以使用<svg></svg><symbol></symbol>标签来完成。<symbol></symbol>标签用于定义SVG符号,<use></use>标签用于实例化它。这允许您一次定义SVG符号,并在整个HTML中多次重用它。

如何使我的SVG符号更易访问?

要使您的SVG符号更易访问,您应该使用SVG中的<title></title><desc></desc>标签提供替代文本。<title></title>标签为SVG提供简短的描述性标题,<desc></desc>标签提供更长的描述。这些标签由屏幕阅读器读取,并为视力障碍用户提供重要的上下文。

我可以在CSS中使用SVG符号吗?

是的,SVG符号可以用作CSS中的背景图像。这可以通过将SVG编码为数据URL并将其用作background-image属性的值来完成。但是,此方法不允许您使用CSS设置SVG的样式或对其进行动画处理。

如何优化我的SVG符号以提高性能?

有几种方法可以优化您的SVG符号以提高性能。首先,您可以压缩SVG代码以减小其文件大小。其次,您可以使用gzip压缩进一步减小文件大小。最后,您可以使用HTTP/2来服务您的SVG,这允许更快、更高效的数据传输。

我可以在JavaScript中使用SVG符号吗?

是的,SVG符号可以用JavaScript进行操作。这允许您动态更改SVG的属性,例如其颜色、大小、位置和可见性。您还可以使用JavaScript来动画化SVG、创建交互式SVG和动态加载SVG。

如何创建响应式SVG符号?

要创建响应式SVG符号,您应该为SVG的宽度和高度使用相对单位(如百分比),而不是绝对单位(如像素)。这允许SVG与其父元素一起缩放。您还可以使用viewBox属性指定SVG的纵横比和坐标系,这允许它按比例缩放。

以上是'可重新连接的SVG符号:如何制作它们(以及为什么)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板