前言

不熟悉 Icon 的可以先看这篇 CSS – Icon

Material Design 有自己的一套 Icon 设计。Angular Material 默认就使用这一套。

不过呢,目前 v17.2.0 用的是旧版本的的设计 -- Material Icons

Material Design 3 推出了新版本的设计 -- Material Symbols

本篇会教如何使用旧的 Material Icons,新的 Material Symbols,还有 SVG 版 Icon。

Angular Material for Material Icons (旧设计)

要在 Angular 项目中使用 Material Icons 并不一定要搭配 Angular Material。

Without Angular Material

首先在 index.html 添加 link

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

App Template

<span class="material-icons">home</span>

App Styles

.material-icons {
font-size: 56px;
color: red;
}

效果

Material Icons 是用 font-family 实现的,所以它只需要 CSS Styles 就可以 working 了。

不仅仅是 Material Icons,其它 Icon (e.g. fontawesomeFlaticonionicons) 用法也大同小异。

Do we really need Angualr Material Icon?

Material Icons, fontawesome, Flaticon, ionicons 它们的使用方式已经很简单了,我们还有必要引入 Angualr Material Icon 吗?

不一定,有 3 种情况下使用 Angualr Material Icon 会比较好:

  1. multiple icon library

    一个 icon library 未必可以满足整个项目的需求,比如说我们选了 Material Icons 作为 primary,但有些 icon 或许它没用。

    这时就需要额外加一些 SVG icon 弥补上。

    一旦出现 2 个 library,代码风格管理可能就不统一了,比如 Material Icons 用 <span>,fontawesome 用 <i>,有些又是 <svg>。

    这时用 Angualr Material 组件 <mat-icon> 就可以把它们统一起来。

  2. multiple projects

    不同项目 icon 风格可能会不一样。哪怕它们都使用 Material Symbols 也可能分 Outlined, Rounded, Sharp 不同变种。

    这种情况使用 Angualr Material 组件 <mat-icon> 也可以达到统一管理的目的。

  3. 顺风水

    人家 wrap 一层给你一定是有原因的嘛。

With Angular Material Icon

App 组件 import MatIconModule

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { MatIconModule } from '@angular/material/icon'; @Component({
selector: 'app-root',
standalone: true,
// 1. import MatIconModule
imports: [MatIconModule],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}

App Template

<mat-icon aria-hidden="false" aria-label="home icon" fontIcon="home"></mat-icon>

如果项目不需要支持 screen reader 可以去掉所有 "aria-" attribute。

下面 2 种写法几乎是等价的,唯一的区别好像是 search engine 会以为第一种是 text。

<mat-icon>home</mat-icon>
<mat-icon fontIcon="home" />

Angular Material 推荐我们使用第二种,但是 Google Fonts Icon 给的例子却是第一种,我也不懂要听谁的。

CSS Styles

mat-icon {
color: red;
font-size: 56px;
width: 56px;
height: 56px;
}

修改 size 比较麻烦,需要改 3 个属性 font-size, width, height。

这是因为 <mat-icon> 是 inline-block

inline-block 的作用是在 font-family 加载完成前先卡着位置,这样布局就不会跳一下。

rendered html

<mat-icon _ngcontent-ng-c2283532919="" role="img" class="mat-icon notranslate material-icons mat-ligature-font mat-icon-no-color" aria-hidden="true" data-mat-icon-type="font">home</mat-icon>

<mat-icon> 组件其实也没用替我们做多少事儿,主要就是添加了 class "material-icons"。其它的像 role, aria-hidden 这些是 for accessibility。

Angular Material for Material Symbols (新设计)

Material Symbols 是 Material Design 3 对 Icon 的新设计。

官网依旧是 https://fonts.google.com/icons

它有一个 select options 可以切换回去旧设计。

旧设计有 5 个变种,新设计只有 3 个变种

我选 Rounded 作为例子。

Setup Angular Material

index.html 添加 link 和 styles (去官网拿)

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
<style>
.material-symbols-rounded {
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 24
}
</style>

Material Symbols 的使用代码长这样

<span class="material-symbols-rounded">home</span>

它和 Material Icons 的区别是 class 不一样。

这时我们需要设置 Angular Material Icon 让它知道我们要换掉原本的 class。

App 组件

export class AppComponent {
constructor() {
const iconRegistry = inject(MatIconRegistry);
iconRegistry.setDefaultFontSetClass('material-symbols-rounded');
}
}

MatIconRegistry 是一个 Root Level Provider。通过它我们可以对全局的 <mat-icon> 进行设置。

提醒:这个设置要趁早哦,因为 MatIcon 是在 OnInit 阶段去读取 MatIconRegistry 的,

而且它不会监听 MatIconRegistry 变更,如果错过了 OnInit 只有当 @Input fontIcon 变更才会再读取 MatIconRegistry 了。

个人建议大家可以在 App 组件 constructor 或者 APP_INITIALIZER 阶段去设置 MatIconRegistry。

App Template

<mat-icon>home</mat-icon>

这里和 Material Icons 是一模一样的,我们只需要设置 MatIconRegistry 就可以了,它会负责修改所有 <mat-icon> 的逻辑。

效果

注意:如果使用 fontIcon attribute 的话

<mat-icon fontIcon="home" />

MatIconRegistry 还需要添加多一个 class "mat-ligature-font" 才行。

const iconRegistry = inject(MatIconRegistry);
iconRegistry.setDefaultFontSetClass('material-symbols-rounded', 'mat-ligature-font');

相关文档 Docs – MatIcon

class "mat-ligature-font" 是输出伪元素的 selector,所以使用 fontIcon 的写法就必须搭配它。

Use both Material Symbols and Material Icons

如果我们想同时使用 2 种不同的 Icon Library 也是可以的。

export class AppComponent {
constructor() {
const iconRegistry = inject(MatIconRegistry);
iconRegistry.registerFontClassAlias('symbols', 'material-symbols-rounded mat-ligature-font');
}
}

上一 part 我们用 MatIconRegistry.setDefaultFontSetClass 替换了默认的设置,

这里我们改用 registerFontClassAlias 添加一个设置。

使用方式

<!-- 用默认的 Material Icons -->
<mat-icon fontIcon="home" /> <!-- 用新的 Material Symbols -->
<mat-icon fontIcon="home" fontSet="symbols" />

通过 fontset="name" 来表明用哪一个,这个 name 就是上面 registerFontClassAlias 的注册的名字。

效果

Fill mode

Fill mode 就是有填满颜色,如上图所示。

我们在 index.html 的 styles 里头有一个 'FILL'

<style>
.material-symbols-rounded {
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 24
}
</style>

它就是用来配置全局 fill mode 的,0 代表 false 不要 fill,1 代表 true 要 fill。

想要针对某一个 icon 做修改也可以

mat-icon.fill {
font-variation-settings: 'FILL' 1;
}

直接 override 就是了。

题外话:Self Hosting for Material Symbols

这个和 Angular Material Icon 无关,我只是顺便提一下。

上面 index.html 引入的 link,它的具体内容是

我们下载它的 .woff2 放到自己的 server,然后把 style 代码写进 style.scss 就可以了。

Angular Material SVG Icon

假设有 2 个 SVG icons

我们想使用 <mat-icon> 来统一输出它们。

addSvgIcon

App Template

<mat-icon svgIcon="home" />
<mat-icon svgIcon="toggle_on" />

把原本的 fontIcon attribute 改成 svgIcon attribute。

然后用 MatIconRegistry 做设置

export class AppComponent {
constructor() {
const iconRegistry = inject(MatIconRegistry);
const domSanitizer = inject(DomSanitizer);
// 1. 需要 bypass 消毒
const homeSvgUrl = domSanitizer.bypassSecurityTrustResourceUrl('/assets/icons/home.svg');
const toggleOnSvgUrl = domSanitizer.bypassSecurityTrustResourceUrl('/assets/icons/toggle_on.svg'); // 2. 一个一个添加
iconRegistry.addSvgIcon('home', homeSvgUrl);
iconRegistry.addSvgIcon('toggle_on', toggleOnSvgUrl);
}
}

不熟悉消毒的朋友可以看这篇:DomSanitizer

效果

它会用 HttpClient 发请求去下载 SVG file。

提醒:我们需要 provide HttpClient 哦。

addSvgIconInNamespace

SVG file 通常会来自四面八方不同的设计,多了就很乱,Angular Material Icon 提供了一个 namespace 概念帮助管理。

iconRegistry.addSvgIconInNamespace('my-design', 'home', homeSvgUrl);
iconRegistry.addSvgIconInNamespace('my-design', 'toggle_on', toggleOnSvgUrl);

把 addSvgIcon 换成 addSvgIconInNamespace,并且提供一个 namespace 名字

使用方式

<mat-icon svgIcon="my-design:home" />
<mat-icon svgIcon="my-design:toggle_on" />

多了一个 "my-design:" prefix。

addSvgIconLiteral or addSvgIconLiteralInNamespace

除了可以提供 SVG URL,我们也可以直接提供 SVG element。(提醒:一样要消毒)

const homeSvgHtml = domSanitizer.bypassSecurityTrustHtml(`
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z"/></svg>
`);
iconRegistry.addSvgIconLiteralInNamespace('my-design', 'home', homeSvgHtml);

这样它就不需要 HttpClient 发请求去下载了。

addSvgIconSet or addSvgIconSetInNamespace

SVG 有一个概念叫 sprite,就是把多个 SVG combine 在一个 SVG file 里,这样就一次性下载多个 SVG。

我们把 home.svg 和 toggle_on.svg combine 成 1 个 sprite.symbol.svg。

使用 addSvgIconSet or addSvgIconSetInNamespace 做设置

const svgSpriteUrl = domSanitizer.bypassSecurityTrustResourceUrl(
'/assets/icons/svg-icon-sprite/symbol/svg/sprite.symbol.svg',
);
iconRegistry.addSvgIconSetInNamespace('my-design', svgSpriteUrl);

效果

2 个 SVG icons 只需要下载一个 sprite svg file。

提醒:Angular Material Icon 并不知道 sprite svg file 的具体内容,它会一次性下载所有 sprite svg file。

多出的 4px

Template

<div class="container">
<mat-icon fontIcon="home" />
</div>

Styles

.container {
background-color: pink; mat-icon {
background-color: lightblue;
}
}

效果

icon 下方粉色的部分就是多出来的 4px。

原因是 <mat-icon> 是 display: inline-block

vertical-align: baseline 情况下就会出现 4px,更多原理可以看这篇

如果不希望出现这个 4px,可以给 <mat-icon> 设置 display: block,或者 vertical-align: bottom。

mat-icon {
background-color: lightblue;
vertical-align: bottom;
/* display: block; */
}

效果

总结

本篇介绍了如何使用 Angular Material Icon 做 Icon 统一管理。

不管是不同的 Icon Library (Material 新 vs Material 旧)

或者不同输出方式 (font-family vs SVG)

Angular Material Icon 都统一了 <mat-icon> 的接口。大部分情况我们只需要对全局的 MatIconRegistry 做设置管理就可以了。

目录

上一篇 Angular Material 18+ 高级教程 – CDK Scrolling

下一篇 Angular Material 18+ 高级教程 – Material Ripple

想查看目录,请移步 Angular 18+ 高级教程 – 目录

喜欢请点推荐,若发现教程内容以新版脱节请评论通知我。happy coding

Angular Material 18+ 高级教程 – Material Icon的更多相关文章

  1. ios cocopods 安装使用及高级教程

    CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...

  2. 分享25个新鲜出炉的 Photoshop 高级教程

    网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...

  3. Siki_Unity_2-9_C#高级教程(未完)

    Unity 2-9 C#高级教程 任务1:字符串和正则表达式任务1-1&1-2:字符串类string System.String类(string为别名) 注:string创建的字符串是不可变的 ...

  4. Pandas之:Pandas高级教程以铁达尼号真实数据为例

    Pandas之:Pandas高级教程以铁达尼号真实数据为例 目录 简介 读写文件 DF的选择 选择列数据 选择行数据 同时选择行和列 使用plots作图 使用现有的列创建新的列 进行统计 DF重组 简 ...

  5. 【读书笔记】.Net并行编程高级教程(二)-- 任务并行

    前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...

  6. 【读书笔记】.Net并行编程高级教程--Parallel

    一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机 ...

  7. 展讯NAND Flash高级教程【转】

    转自:http://wenku.baidu.com/view/d236e6727fd5360cba1adb9e.html 展讯NAND Flash高级教程

  8. Net并行编程高级教程--Parallel

    Net并行编程高级教程--Parallel 一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控 ...

  9. [转帖]tar高级教程:增量备份、定时备份、网络备份

    tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...

  10. Django 2.0.1 官方文档翻译: 高级教程:如何编写可重用的app (page 13)

    高级教程:如何编写可重用的app (page 13) 本节教程上接第七部分(Page 12).我们会把我们的 web-poll应用转换成一个独立的python包,你可以在新的项目中重用或者把它分享给其 ...

随机推荐

  1. 【进阶篇】一文搞清楚网页发起 HTTP 请求调用的完整过程

    目录 前言 一.HTTP协议 1.1基本概念 1.2工作原理 二.请求过程 2.1域名解析 2.2TCP 连接 2.3发送 HTTP 请求 2.4服务器应答 2.5响应内容 2.6关闭连接 三.客户端 ...

  2. [oeasy]python0115_西里尔字符集_Cyrillic_俄文字符编码_KOI_8859系列

    各语言字符编码 回忆上次内容 上次回顾了 非ascii的拉丁字符编码的进化过程 0-127 是 ascii 的领域   西欧.北欧语言 大多使用 拉丁字符 由iso组织 制定iso-8859-1   ...

  3. 胜未来:国内大模型+Agent应用案例精选,以及主流Agent框架开源项目推荐

    智胜未来:国内大模型+Agent应用案例精选,以及主流Agent框架开源项目推荐 Agent是以大模型为核心的智能体,通过与用户对话的形式,来完成各种任务,它很像一个"人".如果和 ...

  4. js实现动态表格的添加

    <!DOCTYPE html> <html lang="en"> <head> <title>Table_Simple CSS fo ...

  5. 【英伟达】GTC 2024|黄仁勋2小时演讲精华版|六大亮点| Blackwell GPU | DGX B200 | NVL72 | cuLitho | GROOT | Omniverse Cloud —— 智能机器人元年

    视频地址: https://www.youtube.com/watch?v=zBIddyiMXsU

  6. 如何使用工具下载B站非会员视频(下载B站免费web视频)

    最近准备从B站上下载几个web页面上的视频,但是B站的视频又没有提供相关的下载工具,于是找到了一款下载B站视频的工具( you-get ), 该工具不能下载会员版的视频,不能下载收费的视频,不过对于免 ...

  7. 记录实验室深度学习服务器显卡硬件故障的排查——RmInitAdapter failed! rm_init_adapter failed

    实验室突然通知我说是深度学习的服务器无法查看GPU,并且在GPU上运行的程序也halt on,需要解决.于是查询服务器的运行日志得到下面的信息: Nov 10 01:33:23 dell kernel ...

  8. 【VMware ESXi】把硬盘当内存用?VMware 内存分层(Memory Tiering),你值得拥有!

    VMware vSphere 8.0 U3 发布了一个非常有意义的功能叫内存分层(Memory Tiering),以利用基于 PCIe 的 NVMe 设备充当第二层(辅助)内存,从而使 ESXi 主机 ...

  9. EF Core连接PostgreSQL数据库

    PostgreSQL数据库介绍 PostgreSQL是一个功能强大的开源对象关系型数据库管理系统(RDBMS).最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生,PostgreSQL以 ...

  10. 树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理_虚拟地址、BCM2835芯片手册知识

    微机总线地址 地址总线: 百度百科解释: 地址总线 (Address Bus:又称:位址总线) 属于一种电脑总线 (一部份),是由CPU 或有DMA 能力的单元,用来沟通这些单元想要存取(读取/写入) ...