前言

不熟悉 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. 使用scikit-learn构建模型

    sklearn中还存在许多不同的机器学习模型可以直接调用,相比于自己撰写代码,直接使用sklearn的模型可以大大提高效率. sklearn中所有的模型都有四个固定且常用的方法,分别是model.fi ...

  2. 测试人必会 K8S 操作之 Dashboard

    在云计算和微服务架构的时代,Kubernetes (K8S) 已成为管理容器化应用的标准.然而,对于许多新手来说,K8S 的操作和管理常常显得复杂而神秘.特别是,当你第一次接触 K8S Dashboa ...

  3. 深入理解 JavaScript 闭包:前端开发中的重要概念

    闭包是 JavaScript 中一个非常重要的概念,对于理解和编写高效.灵活的代码至关重要.尽管它看似复杂,但一旦掌握了闭包,你将能够更好地理解 JavaScript 的函数作用域和变量生命周期.本文 ...

  4. apache ab.exe压力测试

    ab.exe是一个性能检测工具,是apache server中的一个小组件,使用简单,方便     下载地址:http://files.cnblogs.com/files/gossip/ab.zip ...

  5. 微信小程序热门选题

    一.大体实现思路 微信小程序,现在是非常热门的,基于微信生态开发的.现在很多计算机毕业的同学,都会选择微信小程序作为毕业设计 小程序端通常都是展示数据给用户去看的,大多数情况下,这些数据不是写死的,而 ...

  6. oeasy教您玩转vim - 21 - 状态横条

    状态横条 回忆上节课内容 我们上次研究了标尺 标尺 开启 se ru 关闭 se noru 行号 开启 se nu 关闭 se nonu 命令位置 开启 se showcmd 关闭 se noshow ...

  7. 我从 Python 潮流周刊提取了 800 个链接,精选文章、开源项目、播客视频集锦

    你好,我是豌豆花下猫.前几天,我重新整理了 Python 潮流周刊的往期分享,推出了第 1 季的图文版电子书,受到了很多读者的一致好评. 但是,合集和电子书的篇幅很长,阅读起来要花不少时间.所以,为了 ...

  8. JavaScript小面试~数组相关的方法和运用(学习笔记)

    1,稀疏数组 稀疏数组是指数组中的某个下标未给出值或某个下标的值被删除.例如: let arrayOne=['xiaozi',,12,,true,23] let arrayTwo=[1,2,3,3,4 ...

  9. [UE源码] 关于使用UE待改进的一些尝试

    UE从自己做了一款游戏后,发现了蓝图以及UE引擎本身的一些优缺点: 1.蓝图在一些简单的逻辑上书写方便,直观,而且编译速度快,但是也有一些其他问题: 结构体赋值后,无法二次修改 只有3种容器Array ...

  10. 从零开始写 Docker(十九)---增加 cgroup v2 支持

    本文为从零开始写 Docker 系列第十九篇,添加对 cgroup v2 的支持. 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 d ...