Angular2 SVG xlink:href
Angular2 SVG xlink:href
我有渲染 SVG 图标的组件:
import {Component, Directive} from 'angular2/core';
import {COMMON_DIRECTIVES} from 'angular2/common';
@Component({
selector: '[icon]',
directives: [COMMON_DIRECTIVES],
template: `<svg role="img" class="o-icon o-icon--large">
<use [xlink:href]="iconHref"></use>
</svg>{{ innerText }}`
})
export class Icon {
iconHref: string = 'icons/icons.svg#menu-dashboard';
innerText: string = 'Dashboard';
}
这会触发错误:
EXCEPTION: Template parse errors:
Can't bind to 'xlink:href' since it isn't a known native property ("<svg role="img" class="o-icon o-icon--large">
<use [ERROR ->][xlink:href]=iconHref></use>
</svg>{{ innerText }}"): SvgIcon@1:21
如何设置动态 xlink:href
?
SVG 元素没有属性,因此大多数时候都需要属性绑定(另请参阅 Properties and Attributes in HTML)。
对于属性绑定,您需要
<use [attr.xlink:href]="iconHref">
或
<use attr.xlink:href="{{iconHref}}">
更新
清理可能会导致问题。
另见
- https://github.com/angular/angular/issues/9510)
- https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizationService-class.html
Update DomSanitizationService
将在 RC.6
中重命名为 DomSanitizer
更新 这应该是固定的
但是有一个未解决的问题来支持命名空间属性 https://github.com/angular/angular/pull/6363/files
作为解决方法,添加一个额外的
xlink:href=""
Angular 可以更新属性,但添加有问题。
如果 xlink:href
实际上是一个 属性 那么您的语法在添加 PR 后也应该有效。
我仍然对 attr.xlink:href 有问题,Gunter so I created a directive that is similar to SVG 4 Everybody 描述但它是 angular2 特有的。
用法
<div [useLoader]="'icons/icons.svg#menu-dashboard'"></div>
说明
该指令将
- 通过 http
加载 icons/icons.svg
- 解析#menu-dashboard 的响应并提取路径信息
- 将解析后的svg图标添加到html
代码
import { Directive, Input, ElementRef, OnChanges } from '@angular/core';
import { Http } from '@angular/http';
// Extract necessary symbol information
// Return text of specified svg
const extractSymbol = (svg, name) => {
return svg.split('<symbol')
.filter((def: string) => def.includes(name))
.map((def) => def.split('</symbol>')[0])
.map((def) => '<svg ' + def + '</svg>')
}
@Directive({
selector: '[useLoader]'
})
export class UseLoaderDirective implements OnChanges {
@Input() useLoader: string;
constructor (
private element: ElementRef,
private http: Http
) {}
ngOnChanges (values) {
if (
values.useLoader.currentValue &&
values.useLoader.currentValue.includes('#')
) {
// The resource url of the svg
const src = values.useLoader.currentValue.split('#')[0];
// The id of the symbol definition
const name = values.useLoader.currentValue.split('#')[1];
// Load the src
// Extract interested svg
// Add svg to the element
this.http.get(src)
.map(res => res.text())
.map(svg => extractSymbol(svg, name))
.toPromise()
.then(svg => this.element.nativeElement.innerHTML = svg)
.catch(err => console.log(err))
}
}
}
我认为可以使用 angular 管道功能来解决。
<use attr.xlink:href={{weatherData.currently.icon|iconpipe}}></use>
说明
此管道将
- 将解析后的响应值传递给管道
- Return 完整的 svg 路径
attr.xlink:href=
将获得预期的路径 & svg 将呈现在
html 页
这里是管道打字稿代码
import { PipeTransform, Pipe } from '@angular/core';
@Pipe({
name: 'iconpipe'
})
export class IconPipe implements PipeTransform {
constructor() { }
transform(value: any) {
let properIconName = undefined;
switch (value) {
case 'clear-day':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
case 'clear-night':
properIconName = '/assets/images/weather-SVG-sprite.svg#night-1';
break;
case 'partly-cloudy-day':
properIconName = '/assets/images/weather-SVG-sprite.svg#cloudy';
break;
case 'partly-cloudy-night':
properIconName = '/assets/images/weather-SVG-sprite.svg#night';
break;
case 'cloudy':
properIconName = '/assets/images/weather-SVG-sprite.svg#cloud';
break;
case 'rain':
properIconName = '/assets/images/weather-SVG-sprite.svg#rain';
break;
case 'sleet':
properIconName = '/assets/images/weather-SVG-sprite.svg#snowflake';
break;
case 'snow':
properIconName = '/assets/images/weather-SVG-sprite.svg#snowing';
break;
case 'wind':
properIconName = '/assets/images/weather-SVG-sprite.svg#storm';
break;
case 'fog':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
case 'humid':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
default:
properIconName = '/assets/images/weather-SVG-sprite.svg#summer';
}
return properIconName;
}
}
我有渲染 SVG 图标的组件:
import {Component, Directive} from 'angular2/core';
import {COMMON_DIRECTIVES} from 'angular2/common';
@Component({
selector: '[icon]',
directives: [COMMON_DIRECTIVES],
template: `<svg role="img" class="o-icon o-icon--large">
<use [xlink:href]="iconHref"></use>
</svg>{{ innerText }}`
})
export class Icon {
iconHref: string = 'icons/icons.svg#menu-dashboard';
innerText: string = 'Dashboard';
}
这会触发错误:
EXCEPTION: Template parse errors:
Can't bind to 'xlink:href' since it isn't a known native property ("<svg role="img" class="o-icon o-icon--large">
<use [ERROR ->][xlink:href]=iconHref></use>
</svg>{{ innerText }}"): SvgIcon@1:21
如何设置动态 xlink:href
?
SVG 元素没有属性,因此大多数时候都需要属性绑定(另请参阅 Properties and Attributes in HTML)。
对于属性绑定,您需要
<use [attr.xlink:href]="iconHref">
或
<use attr.xlink:href="{{iconHref}}">
更新
清理可能会导致问题。
另见
- https://github.com/angular/angular/issues/9510)
- https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizationService-class.html
Update DomSanitizationService
将在 RC.6
DomSanitizer
更新 这应该是固定的
但是有一个未解决的问题来支持命名空间属性 https://github.com/angular/angular/pull/6363/files
作为解决方法,添加一个额外的
xlink:href=""
Angular 可以更新属性,但添加有问题。
如果 xlink:href
实际上是一个 属性 那么您的语法在添加 PR 后也应该有效。
我仍然对 attr.xlink:href 有问题,Gunter so I created a directive that is similar to SVG 4 Everybody 描述但它是 angular2 特有的。
用法
<div [useLoader]="'icons/icons.svg#menu-dashboard'"></div>
说明
该指令将
- 通过 http 加载 icons/icons.svg
- 解析#menu-dashboard 的响应并提取路径信息
- 将解析后的svg图标添加到html
代码
import { Directive, Input, ElementRef, OnChanges } from '@angular/core';
import { Http } from '@angular/http';
// Extract necessary symbol information
// Return text of specified svg
const extractSymbol = (svg, name) => {
return svg.split('<symbol')
.filter((def: string) => def.includes(name))
.map((def) => def.split('</symbol>')[0])
.map((def) => '<svg ' + def + '</svg>')
}
@Directive({
selector: '[useLoader]'
})
export class UseLoaderDirective implements OnChanges {
@Input() useLoader: string;
constructor (
private element: ElementRef,
private http: Http
) {}
ngOnChanges (values) {
if (
values.useLoader.currentValue &&
values.useLoader.currentValue.includes('#')
) {
// The resource url of the svg
const src = values.useLoader.currentValue.split('#')[0];
// The id of the symbol definition
const name = values.useLoader.currentValue.split('#')[1];
// Load the src
// Extract interested svg
// Add svg to the element
this.http.get(src)
.map(res => res.text())
.map(svg => extractSymbol(svg, name))
.toPromise()
.then(svg => this.element.nativeElement.innerHTML = svg)
.catch(err => console.log(err))
}
}
}
我认为可以使用 angular 管道功能来解决。
<use attr.xlink:href={{weatherData.currently.icon|iconpipe}}></use>
说明 此管道将
- 将解析后的响应值传递给管道
- Return 完整的 svg 路径
attr.xlink:href=
将获得预期的路径 & svg 将呈现在 html 页
这里是管道打字稿代码
import { PipeTransform, Pipe } from '@angular/core';
@Pipe({
name: 'iconpipe'
})
export class IconPipe implements PipeTransform {
constructor() { }
transform(value: any) {
let properIconName = undefined;
switch (value) {
case 'clear-day':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
case 'clear-night':
properIconName = '/assets/images/weather-SVG-sprite.svg#night-1';
break;
case 'partly-cloudy-day':
properIconName = '/assets/images/weather-SVG-sprite.svg#cloudy';
break;
case 'partly-cloudy-night':
properIconName = '/assets/images/weather-SVG-sprite.svg#night';
break;
case 'cloudy':
properIconName = '/assets/images/weather-SVG-sprite.svg#cloud';
break;
case 'rain':
properIconName = '/assets/images/weather-SVG-sprite.svg#rain';
break;
case 'sleet':
properIconName = '/assets/images/weather-SVG-sprite.svg#snowflake';
break;
case 'snow':
properIconName = '/assets/images/weather-SVG-sprite.svg#snowing';
break;
case 'wind':
properIconName = '/assets/images/weather-SVG-sprite.svg#storm';
break;
case 'fog':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
case 'humid':
properIconName = '/assets/images/weather-SVG-sprite.svg#sun';
break;
default:
properIconName = '/assets/images/weather-SVG-sprite.svg#summer';
}
return properIconName;
}
}