我正在尝试使用Angular Material 7.2和Angular 7.2.11实现具有自定义SVG图标的按钮。使用标准的Material图标字体我没有遇到任何问题。但是,自定义图标只会导致控制台上出现“错误检索图标:<svg>
标记”。
我一直在浏览@ angular / material / esm2015 / icon.js中的代码,发现_fetchUrl()似乎正在接收SVG,但是尽管ACTUAL响应包含以下内容,但HttpResponse对象的主体为空: Firefox验证的SVG。 HttpResponse对象中的标头包含正确的内容长度。
将HttpResponse对象报告的URL粘贴到浏览器中会呈现正确的SVG。
_fetchUrl()使用HttpClient :: get()的'text'responseType选项,据我所知,尽管响应指定了content-type: image/svg+xml
,这还是可以的。可以肯定的是,我重命名了SVG,并为其赋予了“ txt”扩展名。后续响应的内容类型为text/plain
,但是HttpResponse的正文仍然为空。
从等式中删除Material图标注册表,而仅尝试简单的get()
会产生相同的问题。请求成功完成,发送了SVG,但是HttpResponse的正文为空。
应用程序模块:
import { HttpClientModule, ... } from '@angular/common/http';
import {
...
MatIconModule,
...
} from '@angular/material';
@NgModule({
...
imports: [
...
HttpClientModule,
MatIconModule
...
],
...
})
应用程序组件:
@Component({
...
})
export class AppComponent {
constructor(private router: Router, private matIconRegistry: MatIconRegistry, private domSanitizer: DomSanitizer, private http: HttpClient, ...)
{
this.matIconRegistry.addSvgIcon('test_icon',
this.domSanitizer.bypassSecurityTrustResourceUrl('/assets/svg/test.svg'));
http.get('/assets/svg/test.svg', { responseType: 'text' }) .subscribe(svg => console.log(`Response: ${svg}`));
}
}
组件HTML:
<button mat-icon-button>
<mat-icon svgIcon="test_icon"></mat-icon>
</button>
测试SVG文件:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="64" height="64" style="fill:rgb(0,0,0,0)" />
</svg>
<svg>Test</svg>
控制台输出:
Request to access cookie or storage on “https://fonts.googleapis.com/icon?family=Material+Icons” was blocked because we are blocking all third-party storage access requests and content blocking is enabled. calendar
Angular is running in the development mode. Call enableProdMode() to enable the production mode. core.js:21273
Error retrieving icon: <svg> tag not found icon.js:867:81
请求/响应:
GET /assets/svg/test.svg HTTP/1.1
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Accept-Ranges: bytes
Content-Type: image/svg+xml; charset=UTF-8
Content-Length: 219
ETag: W/"d9-8SqOE9sCdf/cpMgr8wAdHVFXV+g"
Date: Tue, 02 Apr 2019 00:36:12 GMT
Connection: keep-alive
<?xml version="1.0" encoding="utf-8" ?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<rect x="0" y="0" width="32" height="32" style="fill:rgb(0,0,0,0)" />
</svg>
答案 0 :(得分:1)
您可以按照此代码段在材料注册表中添加自定义材料图标。 图标 我正在维护一个枚举图标列表并用于加载图标方法。 步骤 1:首先创建一个 IconService。
<style name="ThemeOverlay.App.Toolbar" parent="ThemeOverlay.MaterialComponents.Toolbar.Primary">
<!-- color used by navigation icon and overflow icon -->
<item name="colorOnPrimary">@color/myColor</item>
</style>
第 2 步:在提供者部分下的 app.module.ts 中注入服务
import { Injectable } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { environment } from 'src/environments/environment';
import { Icons } from '../../enums/icons.enum';
@Injectable({
providedIn: 'root'
})
export class IconService {
baseURL: string = environment.baseURL;
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) { }
public registerIcons(): void {
this.loadIcons(Object.values(Icons), this.baseURL + 'assets/svg/icons');
}
private loadIcons(iconKeys: string[], iconUrl: string): void {
iconKeys.forEach(key => {
debugger;
this.matIconRegistry.addSvgIcon(key, this.domSanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${key}.svg`));
});
}
}
<块引用>
第 3 步:在构造函数 app.component.ts 文件中注入图标服务并调用 registerIcons 方法
@NgModule({
declarations: [
AppComponent,
NavMenuComponent
],
imports: [
AppRoutes,
NgbModule,
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
HttpClientModule,
FormsModule,
BrowserAnimationsModule,
MatMenuModule,
MatSidenavModule,
MatIconModule,
MatTooltipModule,
ToastrModule.forRoot(),
],
providers: [ ToastrService , CookieService, ErrorService, HttpService, StorageService, IconService
],
bootstrap: [AppComponent]
})
export class AppModule { }
答案 1 :(得分:0)
this.domSanitizer.bypassSecurityTrustResourceUrl('./assets/svg/test.svg'));
您看到区别了吗?
答案 2 :(得分:0)
最后,将问题追溯到项目中的HTTP拦截器。它消除了响应的主体。