用SVG图形替换mat-icon

14
Angular 新手在这里.. 有人能指引我正确的方法如何用 SVG 图形将现有的 Material 图标适当地替换为自定义图标吗? 像这样:
<mat-icon class="mat-icon-rtl-mirror">
     {{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
这样做:
<mat-icon class="mat-icon-rtl-mirror">
     {{nestedTreeControl.isExpanded(node) ? 'INSERT_SVG_1_HERE' : 'INSERT_SVG_2_HERE'}}
</mat-icon>
3个回答

13

不幸的是,这不能完全解决您的问题,因为您需要在mat-icon元素上使用参数svgIcon,而不是使用mat-iconinnerText,但其他方面它可以工作:

  1. 必须允许Angular通过声明模块来导入svg。
  2. 要将图标导入/内联到JavaScript中,您将需要覆盖加载器。这可以通过使用raw-loader来实现。
  3. 现在,您将能够将svg导入Angular并通过MatIconRegistry注册它们;

例如:

// src/typings.d.ts

declare module '*.svg' {
  const svg: string;
  export default svg;
}
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DomSanitizer } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { MatIconModule, MatIconRegistry } from '@angular/material';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

import thumbsUp from '!!raw-loader!./thumbs-up.svg';

@NgModule({
  imports:      [ 
    BrowserModule, 
    FormsModule, 
    MatIconModule 
  ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule {
  constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
    iconRegistry.addSvgIconLiteral(
        'thumbsUp', sanitizer.bypassSecurityTrustHtml(thumbsUp));
  }
}
// src/app/app.component.html
<mat-icon svgIcon="thumbsUp"></mat-icon>
// src/app/thumbs-up.svg
<svg>...</svg>

另一种方法是安装@mdi/svg

npm install @mdi/svg

然后按照上述步骤进行,不同之处在于还需要导入每个必要的图标,例如expand_morechevron_right

所以在 src/app/app.module.ts 中进行。

// src/app/app.module.ts
...
import expandMore from '!!raw-loader!@mdi/svg/svg/chevron-down.svg';
import chevronRight from '!!raw-loader!@mdi/svg/svg/chevron-right.svg';
...
export class WeddingDayModule {
  constructor(
    private iconRegistry: MatIconRegistry,
    private sanitizer: DomSanitizer
  ) {
    iconRegistry
      .addSvgIconLiteral('chevron_right', sanitizer.bypassSecurityTrustHtml(chevronRight))
      .addSvgIconLiteral('expand_more', sanitizer.bypassSecurityTrustHtml(expandMore));
  }
 }

在 HTML 中只是简化了一下...但你会明白的...

//src/app/app.component.html
...
<mat-icon [svgIcon]="expanded ? 'chevron_right' : 'expand_more'" (click)="expanded = !expanded"></mat-icon>
...

这种方法的缺点是,您必须注册要使用的所有图标... 但至少您保持在相同的变化领域内。您可以通过svgIcon更改它们而不是使用连字号,并且您会获得比过时的material-design-icons库拥有的更多的图标。

希望这有所帮助。


是的,我知道这种方法,并且我成功地将其用作mat-icon上的svgIcon... 但是我正在尝试找到一种用自定义SVG替换'expand_more':'chevron_right'的方法,以便它可以在条件语句中使用... 不知道是否可能?感谢您的努力,当启用时将授予奖励。 - Smithy
所以如果我理解正确,您想要实现的是找到一种一致的方式,无论是使用自定义 SVG 图标还是“defaultish”材料图标? - Eydrian
是的,所以如果我有一个自定义的美国国旗SVG图形,我希望能够随时将其用作“us_flag_custom”。 - Smithy
好的,那么反过来使用例如 @mdi/svg 如何呢? 然后像上面提到的那样导入Material图标。 那么它们至少可以一致地用作svgIcon's。并不完美,因为您需要注册每个要使用的材料图标... 如果您认为这可以解决问题,我会更新答案。 - Eydrian
是的,请展示一下那种方法也会很有趣。 - Smithy
1
@Smithy 顺便说一下,我刚刚发现你可以毫不费力地混合使用 <mat-icon [svgIcon]="icon">{{ icon }}</mat-icon>,如果没有可用的连字符,则会使用 svgIcon。 - Eydrian

1
你可以使用angular-svg-icon
angular-svg-icon是一个Angular 7服务和组件,提供一种内联SVG文件的方法,使得它们可以轻松地通过CSS和代码进行样式设置。
该服务提供一个图标注册表,加载和缓存由其URL索引的SVG。该组件负责显示SVG。从注册表获取svg后,它会克隆SVGElement和SVG到组件的内部HTML中。
更多信息请参见:https://www.npmjs.com/package/angular-svg-icon

-2

如果它不是材料图标的一部分,为什么不将其用作普通图像呢。 只需像普通图像标记一样使用它:

<img src="{{nestedTreeControl.isExpanded(node) ? 'path_to_svg_file_1.svg' : 'path_to_svg_file_2'}}">

它似乎不是那样工作的...如果我像'../assets/SVG_file.svg'这样插入它,它只显示'../folder'。 - Smithy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接