将 SVG 转换为遮罩
此函数是 Iconify Tools 中 图标操作函数 的一部分。
函数 convertSVGToMask() 将图标内容转换为 Alpha 遮罩,并遮罩一个与图标 viewBox 尺寸相同的矩形。
此函数适用于以下两种场景:
- 将包含多种颜色的图标转换为单色图标时,为不同颜色使用不同的深浅度。
- 修复设计不佳的图标时,该图标使用白色形状代替了透明部分。
遮罩的工作原理
当存在多个形状,且其中一些应为实心、一些应为透明时,遮罩可以提供帮助。 遮罩中的图像将被视为被遮罩形状的 Alpha 通道。
形状中的颜色将被视为 Alpha 通道:白色 (255) 的不透明度为 1,黑色 (0) 的不透明度为 0。其他颜色通过组合其红、绿、蓝通道并除以 255*3 来转换为 Alpha 通道。
例如,此图标包含多个不同颜色的形状(使用黑色背景以确保白色形状可见):
以下是将同一图标用作矩形遮罩,并使用各种颜色渲染的效果:
用于创建此示例的代码可在下方“示例”部分的“按原样转换”演示中找到。
用法
该函数具有以下参数:
- svg,SVG。图标实例。
- options,object。可选配置项。
函数在成功时返回 true,如果图标未转换为遮罩则返回 false。
返回 false 的情况
函数在什么情况下会无法将图标转换为遮罩?
- 如果图标包含未预期的颜色。请确保所有颜色都已通过 solid、transparent 和/或 custom 选项进行处理。
- 如果没有需要遮罩的内容(图标仅有一种颜色)且未启用 force 选项。请使用 parseColors 来更改此类图标的颜色。
配置项
配置项是一个包含以下可选属性的对象:
- id,string。遮罩 ID,默认值为 "mask"。
- force,boolean。如果启用,即使没有需要遮罩的内容,也会强制函数应用遮罩。
- color,string。用于填充遮罩的颜色,默认值为 "#000"。
要告知函数哪些颜色应被视为实心、透明或半透明,请使用以下选项:
- solid,string|string[]|function。实心颜色:字符串、字符串数组或回调函数。
- transparent,string|string[]|function。透明颜色:字符串、字符串数组或回调函数。
- custom,function。回调函数,应为图标中找到的颜色返回遮罩颜色或不透明度。
默认情况下,黑色被视为实心,白色被视为透明(这与遮罩的工作原理相反,但正是大多数存在缺陷的图标的设计方式),图标中发现的所有其他颜色都会导致函数失败。
使用 custom 选项时,如果 custom 不处理未知颜色,您可能希望禁用 solid 和 transparent 选项的默认值。为此,请将它们设置为空数组。
实心与透明
solid 和 transparent 可以是:
- string,例如 "#fff"
- string[],例如 ["#fff", "black"]
- function,接受颜色字符串作为参数,并返回 true(如果颜色应为实心/透明)或 false(如果颜色不应为实心/透明)
颜色值以及传递给回调的颜色始终为小写。因此,如果您的图标使用 "#FFF",请检查 "#fff"。
自定义
当 solid 和 transparent 均返回 false 时,将使用 custom 属性。
它是一个包含 2 个参数的函数:
- 颜色,类型为 string,小写形式,例如 "#fff"。
- 颜色,类型为 Color 实例。
函数可以返回:
- 颜色,类型为 string,例如实心形状使用 "#fff",透明形状使用 "#000",半透明形状使用任何其他有效颜色。
- 不透明度,类型为 number,介于 0 和 1 之间。函数会将回调返回的不透明度转换为灰度颜色。
solid 和 transparent 属性的默认值可能会干扰 custom 属性,因此请将它们设置为空数组或始终返回 false 的回调函数。
示例
以下示例展示了如何使用该函数。
修复黑/白
此示例修复了设计不佳的图标,这些图标使用黑色表示实心形状,使用白色表示透明形状。
此类图标在 Figma 社区资源提供的图标集中非常普遍:设计师为页面使用白色背景,并且由于图标外部背景也是白色,因此没有注意到形状中包含了白色。
import { SVG, convertSVGToMask } from '@iconify/tools';
const svg = new SVG(
`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 4H10C6.22876 4 4.34315 4 3.17157 5.17157C2.32803 6.01511 2.09185 7.22882 2.02572 9.25H21.9743C21.9082 7.22882 21.672 6.01511 20.8284 5.17157C19.6569 4 17.7712 4 14 4Z" fill="black"/>
<path d="M10 20H14C17.7712 20 19.6569 20 20.8284 18.8284C22 17.6569 22 15.7712 22 12C22 11.5581 22 11.142 21.9981 10.75H2.00189C2 11.142 2 11.5581 2 12C2 15.7712 2 17.6569 3.17157 18.8284C4.34315 20 6.22876 20 10 20Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.25 16C5.25 15.5858 5.58579 15.25 6 15.25H10C10.4142 15.25 10.75 15.5858 10.75 16C10.75 16.4142 10.4142 16.75 10 16.75H6C5.58579 16.75 5.25 16.4142 5.25 16Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 16C11.75 15.5858 12.0858 15.25 12.5 15.25H14C14.4142 15.25 14.75 15.5858 14.75 16C14.75 16.4142 14.4142 16.75 14 16.75H12.5C12.0858 16.75 11.75 16.4142 11.75 16Z" fill="white"/>
</svg>`
);
// Convert to mask, converting black color to solid, white to transparent (default options)
convertSVGToMask(svg);
// Output result
console.log(svg.toString());<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<defs>
<mask id="mask">
<path d="M14 4H10C6.22876 4 4.34315 4 3.17157 5.17157C2.32803 6.01511 2.09185 7.22882 2.02572 9.25H21.9743C21.9082 7.22882 21.672 6.01511 20.8284 5.17157C19.6569 4 17.7712 4 14 4Z" fill="#fff"/>
<path d="M10 20H14C17.7712 20 19.6569 20 20.8284 18.8284C22 17.6569 22 15.7712 22 12C22 11.5581 22 11.142 21.9981 10.75H2.00189C2 11.142 2 11.5581 2 12C2 15.7712 2 17.6569 3.17157 18.8284C4.34315 20 6.22876 20 10 20Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.25 16C5.25 15.5858 5.58579 15.25 6 15.25H10C10.4142 15.25 10.75 15.5858 10.75 16C10.75 16.4142 10.4142 16.75 10 16.75H6C5.58579 16.75 5.25 16.4142 5.25 16Z" fill="#000"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 16C11.75 15.5858 12.0858 15.25 12.5 15.25H14C14.4142 15.25 14.75 15.5858 14.75 16C14.75 16.4142 14.4142 16.75 14 16.75H12.5C12.0858 16.75 11.75 16.4142 11.75 16Z" fill="#000"/>
</mask>
</defs>
<rect mask="url(#mask)" width="24" height="24" fill="currentColor"/>
</svg>如果图标不是使用黑色,而是使用另一种颜色(例如 "#1C274C")设计的,请将其以小写形式添加到 solid 选项中:
convertSVGToMask(svg, {
solid: ['#000', 'black', '#1c274c']
});按原样转换
此示例在不更改任何颜色的情况下对图标进行遮罩处理。它用于创建本页开头使用的遮罩示例:
import { SVG, convertSVGToMask } from '@iconify/tools';
const svg = new SVG(
`<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 20C4.98 20 3.68333 19.4767 2.61 18.43C1.53667 17.3767 1 16.0933 1 14.58C1 13.28 1.39 12.12 2.17 11.1C2.95667 10.08 3.98333 9.43 5.25 9.15C5.67 7.61667 6.50333 6.37667 7.75 5.43C9.00333 4.47667 10.42 4 12 4C13.9533 4 15.6067 4.68 16.96 6.04C18.32 7.39333 19 9.04667 19 11C20.1533 11.1333 21.1067 11.6333 21.86 12.5C22.62 13.3533 23 14.3533 23 15.5C23 16.7533 22.5633 17.8167 21.69 18.69C20.8167 19.5633 19.7533 20 18.5 20" fill="white"/>
<path d="M6.5 18H18.5C19.2 18 19.79 17.7567 20.27 17.27C20.7567 16.79 21 16.2 21 15.5C21 14.8 20.7567 14.21 20.27 13.73C19.79 13.2433 19.2 13 18.5 13H17V11C17 9.62 16.5133 8.44 15.54 7.46C14.5667 6.48667 13.3867 6 12 6C10.62 6 9.44 6.48667 8.46 7.46C7.48667 8.44 7 9.62 7 11H6.5C5.53333 11 4.71 11.3433 4.03 12.03C3.34333 12.71 3 13.5333 3 14.5C3 15.4667 3.34333 16.3 4.03 17C4.71 17.6667 5.53333 18 6.5 18Z" fill="#444"/>
<circle cx="19" cy="19" r="5" fill="red"/>
<path d="M18 16H20V18H22V20H20V22H18V20H16V18H18V16Z" fill="white"/>
</svg>`
);
// Convert to mask without changing any colors, use them as an alpha channel
convertSVGToMask(svg, {
// Set rectangle color to currentColor
color: 'currentColor',
// Use custom option, returning color as is
custom: (color) => color,
});
// Output result
console.log(svg.toString());该图标的演示可在上方“遮罩的工作原理”部分查看。
多种颜色
有时图标会设计为多种颜色。此函数可用于将它们转换为单色图标,将不同颜色用作实心、半透明或透明颜色。
这可以通过使用 custom 选项来实现。
示例(为原始图标使用灰色背景,以确保黑色和白色形状均可见):
以下代码将图标转换为单色图标,将黑色形状渲染为实心,将蓝色和白色渲染为不同的半透明:
import { SVG, convertSVGToMask } from '@iconify/tools';
const svg = new SVG(
`<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="4">
<path fill="#2F88FF" stroke="#000" d="M44.0001 24C44.0001 35.0457 35.0458 44 24.0001 44C18.0266 44 4.00006 44 4.00006 44C4.00006 44 4.00006 29.0722 4.00006 24C4.00006 12.9543 12.9544 4 24.0001 4C35.0458 4 44.0001 12.9543 44.0001 24Z"/>
<path stroke="#fff" d="M14 18L32 18"/>
<path stroke="#fff" d="M14 26H32"/>
<path stroke="#fff" d="M14 34H24"/>
</g>
</svg>`
);
// Convert to mask
convertSVGToMask(svg, {
// Treat black as solid
solid: '#000',
// No transparent colors
transparent: [],
// Custom opacity for other colors
custom: (color) => {
switch (color) {
case '#fff':
return 0.75; // same as returning '#bfbfbf'
case '#2f88ff':
return 0.25; // same as returning '#404040'
}
},
});
// Output result
console.log(svg.toString());结果:
高级示例
如何解析整个图标集并检查错误?
这可以通过使用 IconSet 实例的 forEach() 或 forEachSync() 函数来完成。两个函数都适用,但由于遮罩是同步应用的,因此没有理由使用异步函数,所以 forEachSync() 是更好的选择。
有关代码,请参阅 从 Figma 导入图标集的超长示例。
在该示例中,在使用 parseColors() 解析所有颜色后,会使用 convertSVGToMask()。如果在解析颜色时发现白色或半透明颜色,则会调用 convertSVGToMask() 将图标转换为遮罩。