WordPress 7.1 可以自定义全套 SVG 图标?一篇搞懂注册、渲染与 REST API!

WordPress 7.0 引入了一套内置的 SVG 图标,供区块编辑器及核心 /icon(图标)区块使用,到 7.1 版本,这套图标集演变成了一个正式的公共 API,开发者可以通过该 API 添加自定义图标、对其进行分组、在服务端渲染它们,并能通过 REST API 读取这些图标。

只需在一个地方注册图标后,即可在编辑器、REST API 和自定义的 PHP 代码等多个地方使用,下面将和大家详细讲解 WordPres 图标 API 的主要功能:

  • 创建和删除图标集。
  • 添加和删​​除单个图标。
  • 在图标区块的选择器中按集合浏览图标。
  • 使用 PHP 渲染图标 wp_get_icon()。
  • 用于集合和图标的 REST API 端点。

图标集(Icon collections)

首先每个图标都属于一个图标集,图标集其实就是图标的命名分组,其名称会作为图标的前缀,这使得来自不同来源(WordPress 核心、插件或第三方图标库)的图标可以并存且互不冲突,比如 core/plus 和 my-plugin/plus 这两个相同名字图标得以区分。

此外,WordPress 默认注册了一个名为 core 的集合,其中包含了内置的图标。

创建集合

图标只能添加到已经存在的图标集中,因此首先需要使用 wp_register_icon_collection() 注册图标集:

add_action( 'init', function() {
	wp_register_icon_collection(
		'my-plugin',
		array(
			'label'       => __( 'My Plugin Icons', 'my-plugin' ),
			'description' => __( 'Icons provided by My Plugin.', 'my-plugin' ),
		)
	);
} );

第一个参数是集合名称,名称必须以小写字母或数字开头和结尾,中间可以包含小写字母、数字、连字符(-)和下划线(_)。

第二个参数是一个数组,包含必需的 label(标签)和可选的 description(描述)。

移除集合

使用 wp_unregister_icon_collection() 并传入图标集名称即可移除,移除图标集的同时也会自动移除其中的所有图标,因此无需逐个删除图标。

请在 init 钩子上运行此函数,并设置比注册时更晚的优先级,以确保该集合已经存在:

add_action( 'init', function() {
	wp_unregister_icon_collection( 'my-plugin' );
}, 20 );

图标(Icons)

每个图标名称的格式均为 collection/icon-name(图标集名/图标名),例如 my-plugin/star,在注册图标时,对应的图标集必须已经被注册。

icon-name 部分遵循与集合名称相同的规则:必须以小写字母或数字开头和结尾,中间可包含小写字母、数字、连字符和下划线。

添加图标

使用 wp_register_icon() 注册图标。需要为其提供一个标签以及 SVG 本身,可以作为字符串直接内联提供(content),或者作为 .svg 文件的绝对路径(file_path)。二者择一即可,不能同时提供。

与其它注册函数一样,wp_register_icon() 在成功时返回 true,失败时返回 false,并会抛出解释原因的 _doing_it_wrong() 提示。

会导致注册失败的情况包括:无效的名称、未使用 collection/icon-name 命名空间格式、集合未注册、图标重复、缺少标签、包含不支持的参数键,或者既未提供 content 也未提供 file_path(或两者同时提供)。

SVG 字符串会经过 wp_kses 进行安全清洗过滤,仅保留白名单中的元素:目前仅允许 <svg>、<path> 和 <polygon> 元素生存,且每个元素仅限于一组固定的属性。白名单之外的任何内容(其它元素、内联样式、脚本或事件处理程序)都会被删除。这个白名单目前非常保守,未来可能会有所放宽以覆盖更多形状元素与属性。

需要注意的是,file_path 是延迟读取的,就是说在注册时不会打开文件,只有在首次需要图标内容(例如 REST 检索或渲染)时才会读取。因此,即使文件路径有误,注册也可能会成功;丢失或不可读的文件只会在后续表现为内容为空,而不会在注册阶段触发错误。请确保该路径在图标使用的运行环境中能够正确解析。

图标可以放入任何已注册的集合中。大多数情况下,将它们注册在你自己的图标集下,可以保持它们与核心图标的清晰隔离。

add_action( 'init', function() {
	// 先注册一个自定义集合,然后再向其中添加图标。
	wp_register_icon_collection(
		'my-plugin',
		array(
			'label' => __( 'My Plugin Icons', 'my-plugin' ),
		)
	);

	// 内联 SVG 字符串的图标。
	wp_register_icon(
		'my-plugin/star',
		array(
			'label'   => __( 'Star', 'my-plugin' ),
			'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
		)
	);

	 // 插件附带的 .svg 文件的图标。
	wp_register_icon(
		'my-plugin/heart',
		array(
			'label'     => __( 'Heart', 'my-plugin' ),
			'file_path' => plugin_dir_path( __FILE__ ) . 'icons/heart.svg',
		)
	);
}, );

移除图标

在 init 钩子上(图标注册之后),使用 wp_unregister_icon() 加上图标名称来移除单个图标。与注册函数类似,成功时返回 true,失败时返回 false 并给出 _doing_it_wrong() 提示;唯一的失败情况是该图标尚未注册。

add_action( 'init', function() {
	wp_unregister_icon( 'my-plugin/star' );
}, 20, );

如果要一次性移除某个集合中的所有图标,请直接移除该集合(参考前面的“移除集合”部分)。

图标区块增强功能

核心 Icon(图标)区块中的图标选择器现在会按集合对图标进行分组,因此来自插件和主题的自定义图标会与核心图标并排显示。

每个集合都有独立的选项卡,同时还有一个涵盖所有集合的“全部”(All)选项卡。搜索功能会在当前选中的集合内进行过滤;使用“全部”选项卡可以跨集合进行搜索。切换选项卡时搜索关键字会被保留。

此外,该区块本身还获得了以下增强:

  • 翻转与旋转:区块工具栏现在拥有水平或垂直翻转图标,以及每次将图标旋转 90 度的按钮。
  • 默认图标:新插入的图标区块现在默认以 core/info 开头,而不是空占位符。
  • 通过 wp_get_icon() 进行服务端渲染:区块的服务端渲染现在会委托给 wp_get_icon() 生成 SVG 标记,因此区块渲染的图标与你自己通过 wp_get_icon() 打印的图标走的是同一套代码逻辑。

在 PHP 中渲染图标

使用 wp_get_icon() 获取任何已注册图标的 SVG 标记,以便直接打印:

// 默认 24px 尺寸的装饰性图标。
echo wp_get_icon( 'core/plus' );

// 32px 尺寸、带有无障碍标签和额外 CSS 类的图标。
echo wp_get_icon(
	'my-plugin/star',
	array(
		'size'  => 32,
		'label' => __( 'Featured', 'my-plugin' ),
		'class' => 'my-plugin-star',
	)
);

第一个参数是图标名称,如果未注册,则返回空字符串。

可选的第二个参数接受:

  • size — 宽度和高度(像素),默认为 24,传入 null 可保留 SVG 自身的尺寸。
  • class — 赋予 <svg> 元素的额外 CSS 类名。
  • label — 无障碍标签,如果提供了该项,图标会被读屏软件朗读出来;如果留空,图标会被视为装饰性元素并对读屏软件隐藏。

样式化图标

样式化来自 @wordpress/icons 的 React 图标

自 15.0.0 版本起,每个图标都会在其最外层的 <svg> 上声明 fill="currentColor",因此 React 渲染的图标开箱即用跟随当前文本颜色。默认情况下,图标会继承父级元素的颜色。要应用不同颜色,请设置 color 而不是 fill,就是将 style={{ color }} 传递给图标即可:

import { Icon, plus } from '@wordpress/icons';

<Icon icon={ plus } style={ { color: '#3858e9' } } />;

样式化 wp_get_icon() 返回的 SVG

这部分标记在注册时经过了安全清洗过滤,白名单只保留了 <path> 和 <polygon> 形状上的 fill(最外层 <svg> 上的 fill 不会保留),且不允许任何地方出现 stroke,因此基于描边的图标会丢失其描边,目前你应当尽量使用基于填充的形状。(这是当前的限制:未来可能会放宽白名单以覆盖描边和其它属性)。

这就导致 React 图标在其 <svg> 上携带的 fill="currentColor" 在这里无法保留,且 wp_get_icon() 也不会主动添加它。这会带来两个影响:

  • 在图标区块内部,颜色样式依然有效,因为区块的样式表在 .wp-block-icon svg 上设置了 fill: currentColor。因此区块渲染的图标能正常继承文本颜色。
  • 独立调用 wp_get_icon() 返回的是没有该规则的原始标记,因此默认会以 SVG 自身的填充色(黑色)渲染,而不是周围的文本颜色。

要使独立的图标继承文本颜色,有两种方法:

1. 通过自定义 CSS:在渲染图标时加上类名(wp_get_icon() 会将其放在 <svg> 上),然后对该类设置 fill,由于 fill 是可继承的,它会下钻应用到内部的形状上:

echo wp_get_icon( 'my-plugin/star', array( 'class' => 'my-icon' ) );
.my-icon {
    fill: currentColor;
}

在注册图标时直接将 fill="currentColor" 放在形状上:白名单保留了 <path> 和 <polygon> 上的 fill 属性,因此它能通过安全清洗过滤,无论在哪里渲染,图标都能自带该颜色行为:

wp_register_icon(
	'my-plugin/star',
	array(
		'label'   => __( 'Star', 'my-plugin' ),
		'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
	)
);

REST API

WordPress 后台古腾堡编辑器是通过 REST API 读取图标和集合,我们也可以使用 PHP 代码这样做,这些 REST 端点是只读的,每个路由都是 GET 请求,因此可以浏览已注册的图标和集合,但不能通过 REST 进行注册或修改。

所有端点均位于 wp/v2 下,且需要通过身份验证的用户拥有 edit_posts 权限,或拥有任何在 REST 中可见(show_in_rest)的文章类型的相应编辑权限。

图标集(Collections):

  • GET /wp/v2/icon-collections — 获取所有集合。
  • GET /wp/v2/icon-collections/<collection> — 获取单个集合。

每个集合都会作为一个包含 slug、label 和 description 的对象返回。例如,GET /wp/v2/icon-collections/core 返回:

{
	"slug": "core",
	"label": "WordPress",
	"description": "Default icon collection."
}

图标(Icons):

  • GET /wp/v2/icons — 获取所有图标。(7.0 中引入了 name、label 和 content 字段及 search 参数;7.1 新增了 collection 字段和参数)
  • GET /wp/v2/icons/<collection> — 获取指定集合中的图标。(7.1 新增)
  • GET /wp/v2/icons/<collection>/<name> — 获取单个图标。(7.0 中引入)

每个图标都会作为一个包含 name(完整的 collection/icon-name)、label、content(安全清洗过滤后的 SVG 标记)和 collection(其所属集合的 slug)的对象返回。例如,GET /wp/v2/icons/core/plus 返回:

{
	"name": "core/plus",
	"label": "Plus",
	"content": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewbox=\"0 0 24 24\"><path d=\"M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z\" /></svg>",
	"collection": "core"
}

图标列表还支持两个查询参数:search 用于按名称或标签进行过滤,collection 用于将结果限定在某个集合内。例如:

GET /wp/v2/icons?collection=my-plugin&search=star

多说两句

WordPress 7.1 引入的全新 SVG 图标 API,不仅规范了图标的管理与扩展机制,也让开发者终于能够脱离第三方插件,优雅地实现原生的自定义图标集。无论是在编辑器中构建组件,还是在前端进行服务端渲染,这一 API 都提供了极大的灵活性。

你在 WordPress 怎么使用图标呢?欢迎在评论区留言交流!


©我爱水煮鱼,本站推荐使用的主机:阿里云,国外主机建议使用BlueHost。

本站长期承接 WordPress 优化和建站业务,请联系微信:「chenduopapa」。