前言

不熟悉 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. Pyechart绘图基础

    1.绘制散点图 from pyecharts.charts import Scatter import pyecharts.options as opts import numpy as np x = ...

  2. Vue项目刷新页面 IE/360 浏览器 input输入框不清空问题处理

    本人在项目开发中,遇到IE/360关于input输入框的兼容问题, 背景介绍:html中直接引用vue.js,及相关组件,input内容不为空时,刷新页面,chrome,Firefox显示正常,IE/ ...

  3. Django+forms+html

    在Django中,Form类通常通过继承django.forms.Form或django.forms.ModelForm来定义.当你定义一个表单类时,通常使用Form或ModelForm类,并使用各种 ...

  4. nginx的一些功能

    一.四层(tcp/udp)代理 由于nginx默认是不支持四层代理的因此在安装的时候需要加上对应的模块with-stream ./configure --with-stream # 查看当前nginx ...

  5. holiday week 1

    本周进度总结: JAVA javafx以安装完毕并完成了环境配置 因处于小学期中java暂时搁置学习 自学了部分链表.多线程以及一些C/C++的知识,对部分C++库有了更进一步了解 因多线程的问题将平 ...

  6. 在Linux中清理Buff/cache

    在 Linux 中,缓冲区和缓存是为提高系统性能而保留的,但如果这些缓存过多,可能会消耗大量内存,影响系统的性能.有时候,您可能需要手动清理这些缓存以释放内存.但请注意,通常不建议定期或频繁地这样做, ...

  7. Android studio报错:Failed to allocate a 3213123 byte allocation with 31231 free bytes and 189MB ontil 0OM

    这个问题是运行内存超了 在AndroidManifest中加入 android:hardwareAccelerated="false"android:largeHeap= &quo ...

  8. Mysql函数10-IF

    IF函数用于判断条件是否成立,成立则执行命令1,不成立则执行命令2. 1.sql查询出一列create_time select create_time from goods where id=65 2 ...

  9. 【SpringBoot】16 数据访问P4 整合JPA

    DAO面向SpringData操作 Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问技术, 包括非关系数据库.Map-Reduce 框架.云数据服务等等: 另外也 ...

  10. AI的技术发展:记忆与想象力 —— 【人工智能】记忆、想象与AI | 查兰·兰加纳特 | 心理学与神经科学家 | 人脑如何记忆 | 内部模型 | 稳定可塑性难题 | 想象力的由来 | AI内容传播 | 脑机接口BCI

    原文地址: https://www.youtube.com/watch?v=cHYKbVP1GTQ 加利福尼亚大学戴维斯分校教授.心理学家兼神经科学家查兰·兰加纳特Charan Ranganath,最 ...