Skip to content

replaceIDs()

此函数属于 Iconify Utils 包

函数 replaceIDs() 用于将图标内容中的 ID 替换为随机生成的字符串。

所有图标组件在渲染每个图标时都会使用此函数。

为什么需要它?

ID 用于图标元素中,例如可复用的路径、遮罩、动画。它们应该是唯一的。

当你从图像编辑器导出 SVG 时,编辑器通常会根据图层名称生成 ID,因此如果图层名为 "Mask",形状的 ID 很可能就是 "mask"。图标优化工具(如 SVGO)默认会缩短 ID,因此图标最终会带有类似 "a" 的 ID。

当图标作为外部资源链接时,这不是问题。但是,当图标嵌入到文档中时,来自不同图标的多个元素具有相同的 ID 可能会并且确实会导致混乱。即使在不更改 ID 的情况下在文档的多个位置使用同一个图标,也可能导致错误。

这就是为什么在嵌入图标时,确保每个图标中那些在其他图标中不存在的元素拥有不同的 ID 非常重要。

用法

该函数具有以下参数:

  • contentstring。图标内容。
  • prefixstring|function。生成 ID 的可选前缀。如果你希望自定义 ID 以降低其随机性,请使用此选项。

函数返回替换了 ID 的内容。

在第一个参数中,你可以传递由 iconToSVG() 生成的数据的 body 属性,也可以传递完整的 <svg>

示例

example.ts
tsimport type { FullIconifyIcon } from '@iconify/utils';
import {
   defaultIconProps,
   defaultIconCustomisations,
   iconToSVG,
   replaceIDs,
} from '@iconify/utils';

const iconData: FullIconifyIcon = {
   ...defaultIconProps,
   body: '<defs><linearGradient id="a" x1="4.416" y1="-1909.341" x2="13.909" y2="-1892.9" gradientTransform="translate(0 1917.121)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b72c3f"/><stop offset=".5" stop-color="#b12334"/><stop offset="1" stop-color="#9d1623"/></linearGradient></defs><path d="M8.512 20v6.667c0 1.84 4.81 3.333 10.744 3.333S30 28.507 30 26.667V20z" fill="#881421"/><path d="M8.512 12.667V20c0 1.841 4.81 3.333 10.744 3.333S30 21.841 30 20v-7.333z" fill="#af2031"/><path d="M8.512 5.333v7.334c0 1.84 4.81 3.333 10.744 3.333S30 14.507 30 12.667V5.333z" fill="#c94f60"/><ellipse cx="19.256" cy="5.333" rx="10.744" ry="3.333" fill="#e08095"/><path d="M16.434 8H8.512v16.667h7.922a1.212 1.212 0 0 0 1.194-1.222V9.222A1.212 1.212 0 0 0 16.434 8z" opacity=".1"/><path d="M15.783 8.667H8.512v16.666h7.271a1.212 1.212 0 0 0 1.194-1.222V9.889a1.212 1.212 0 0 0-1.194-1.222z" opacity=".2"/><path d="M15.783 8.667H8.512V24h7.271a1.212 1.212 0 0 0 1.194-1.222V9.889a1.212 1.212 0 0 0-1.194-1.222z" opacity=".2"/><path d="M15.132 8.667h-6.62V24h6.62a1.213 1.213 0 0 0 1.194-1.222V9.889a1.213 1.213 0 0 0-1.194-1.222z" opacity=".2"/><path d="M3.194 8.667h11.938a1.208 1.208 0 0 1 1.194 1.222v12.222a1.208 1.208 0 0 1-1.194 1.222H3.194A1.208 1.208 0 0 1 2 22.111V9.889a1.208 1.208 0 0 1 1.194-1.222z" fill="url(#a)"/><path d="M8.305 12.027h1.758l2.825 7.945h-1.66l-.623-1.895H7.7l-.611 1.895H5.437zm1.926 4.826-.9-2.875a3.812 3.812 0 0 1-.165-.649H9.13a3.729 3.729 0 0 1-.162.671l-.912 2.859z" fill="#fff"/>',
   width: 32,
   height: 32,
};

// Use it to render icon
const renderData = iconToSVG(iconData, defaultIconCustomisations);

// Generate attributes for SVG element
const svgAttributes: Record<string, string> = {
   'xmlns': 'http://www.w3.org/2000/svg',
   'xmlns:xlink': 'http://www.w3.org/1999/xlink',
   ...renderData.attributes,
};
const svgAttributesStr = Object.keys(svgAttributes)
   .map(
       (attr) =>
           // No need to check attributes for special characters, such as quotes,
           // they cannot contain anything that needs escaping.
           `${attr}="${svgAttributes[attr as keyof typeof svgAttributes]}"`
   )
   .join(' ');

// Generate SVG
const svg = replaceIDs(`<svg ${svgAttributesStr}>${renderData.body}</svg>`);

// Log SVG
console.log(svg);
结果:
svg<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1em" height="1em" viewBox="0 0 32 32"><defs><linearGradient id="IconifyId-17c762189ff-239667-0" x1="4.416" y1="-1909.341" x2="13.909" y2="-1892.9" gradientTransform="translate(0 1917.121)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b72c3f"/><stop offset=".5" stop-color="#b12334"/><stop offset="1" stop-color="#9d1623"/></linearGradient></defs><path d="M8.512 20v6.667c0 1.84 4.81 3.333 10.744 3.333S30 28.507 30 26.667V20z" fill="#881421"/><path d="M8.512 12.667V20c0 1.841 4.81 3.333 10.744 3.333S30 21.841 30 20v-7.333z" fill="#af2031"/><path d="M8.512 5.333v7.334c0 1.84 4.81 3.333 10.744 3.333S30 14.507 30 12.667V5.333z" fill="#c94f60"/><ellipse cx="19.256" cy="5.333" rx="10.744" ry="3.333" fill="#e08095"/><path d="M16.434 8H8.512v16.667h7.922a1.212 1.212 0 0 0 1.194-1.222V9.222A1.212 1.212 0 0 0 16.434 8z" opacity=".1"/><path d="M15.783 8.667H8.512v16.666h7.271a1.212 1.212 0 0 0 1.194-1.222V9.889a1.212 1.212 0 0 0-1.194-1.222z" opacity=".2"/><path d="M15.783 8.667H8.512V24h7.271a1.212 1.212 0 0 0 1.194-1.222V9.889a1.212 1.212 0 0 0-1.194-1.222z" opacity=".2"/><path d="M15.132 8.667h-6.62V24h6.62a1.213 1.213 0 0 0 1.194-1.222V9.889a1.213 1.213 0 0 0-1.194-1.222z" opacity=".2"/><path d="M3.194 8.667h11.938a1.208 1.208 0 0 1 1.194 1.222v12.222a1.208 1.208 0 0 1-1.194 1.222H3.194A1.208 1.208 0 0 1 2 22.111V9.889a1.208 1.208 0 0 1 1.194-1.222z" fill="url(#IconifyId-17c762189ff-239667-0)"/><path d="M8.305 12.027h1.758l2.825 7.945h-1.66l-.623-1.895H7.7l-.611 1.895H5.437zm1.926 4.826-.9-2.875a3.812 3.812 0 0 1-.165-.649H9.13a3.729 3.729 0 0 1-.162.671l-.912 2.859z" fill="#fff"/></svg>

前缀

对于第二个参数,你可以使用字符串,它将作为前缀。

如果在上面的示例中,将以下代码:

tsconst svg = replaceIDs(`<svg ${svgAttributesStr}>${renderData.body}</svg>`);

替换为:

tsconst svg = replaceIDs(
   `<svg ${svgAttributesStr}>${renderData.body}</svg>`,
   'my-prefix-'
);

结果将包含类似以下内容:

html<svg ...>
   <linearGradient id="my-prefix-0" x1="4.416" ...>...</linearGradient>
   <path ... fill="url(#my-prefix-0)" />
</svg>

图标将使用自定义前缀并在其后添加一个数字。计数器不会重置,因此每个图标将拥有不同的 ID。

回调函数

你也可以为第二个参数使用回调函数。回调函数接受旧 ID 作为参数,并应返回新 ID:

tslet counter = 0;
const svg = replaceIDs(
   `<svg ${svgAttributesStr}>${renderData.body}</svg>`,
   () => {
       return 'my-prefix-' + counter++;
   }
);

结果将与上面使用前缀字符串的示例完全相同。

另一个示例:

tslet counter = 0;
const svg = replaceIDs(
   `<svg ${svgAttributesStr}>${renderData.body}</svg>`,
   (id: string) => {
       switch (id) {
           case 'a':
               // 将 id="a" 替换为 id="b"
               return 'b';

           default:
               // 对其他 ID 使用 'whatever-' 前缀
               return 'whatever-' + counter++;
       }
   }
);

注意事项

每个图标可以包含任意数量的带有 ID 的元素。如果你使用回调函数生成新 ID,请确保回调函数在每次调用时返回不同的值。