简体   繁体   English

Angular + SVG:如何从字符串动态加载模板

[英]Angular + SVG: how to dynamically load template from string

In Angular, it's possible to use SVG as component template.在 Angular 中,可以使用 SVG 作为组件模板。 I wonder if there is a way to convert a SVG content (string loaded from server) into a component template, including the possibility to bind some properties to it (ie, <tspan [attr.color]="textColor"...>{{myText}}</tspan> ).我想知道是否有办法将 SVG 内容(从服务器加载的字符串)转换为组件模板,包括将一些属性绑定到它的可能性(即<tspan [attr.color]="textColor"...>{{myText}}</tspan> )。

I've made some tests and all that I got was to load and render the SVG content, but the binds are not working.我做了一些测试,我得到的只是加载和渲染 SVG 内容,但绑定不起作用。 Instead, they are rendered as strings.相反,它们被呈现为字符串。

I know that if put the SVG content in a file and reference it in component's templateUrl setting, it works.我知道如果将 SVG 内容放在一个文件中并在组件的templateUrl设置中引用它,它就可以工作。 For example:例如:

...
@Component({
   templateUrl: './content.svg'
})
export class MyComponent {
   ...
}
...

I've already tested it.我已经测试过了。 However, I need to load the SVG from a server (it cannot be a static file or hard coded in source-code).但是,我需要从服务器加载 SVG(它不能是 static 文件或硬编码在源代码中)。

Can anyone help me?谁能帮我?

Update更新

Just to clarify a little bit...只是为了澄清一点......

Consider the following component:考虑以下组件:

@Component({
    selector: 'my-component',
    template: `<div [innerHtml]="mySvg"></div>`
})
export class MyComponent {
    textColor: string;
    myText: string;
    mySvg: string;

    constructor() {
        this.textColor = '#ff0000';
        this.myText = 'Just testing';
    }

    loadSvg() {
        // here goes some logic to request the SVG string from server
        // ...
       this.mySvg = response;
    }
}

Now, consider that the server returned the following string:现在,考虑服务器返回以下字符串:

<svg>
    <tspan [attr.color]="textColor">{{myText}}</tspan>
</svg>

I would like the SVG to be rendered and the interpolations to work as well (making it possible to change the text and color).我希望能够渲染 SVG 并且插值也能正常工作(可以更改文本和颜色)。

Is it possible?可能吗?

If you stick to native standard Javascript template literal notation: ${x}如果您坚持使用本机标准 Javascript 模板文字符号: ${x}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

 `string ${property} string string ${property} string` 

You can create a tagged template function that does all the replacing of property values for you您可以创建一个标记模板 function为您完成所有属性值的替换

Here the template string is the innerHTML , properties as attributes这里的模板字符串innerHTML ,属性作为属性

When you make up your own template syntax (or use 3rd party) You will have to add a lot more boilerplate code or libraries to parse that String当您编写自己的模板语法(或使用第 3 方)时,您将不得不添加更多样板代码或库来解析该字符串

 <svg-from-template cx="30" cy="30"> <rect x='0' y='0' width='100%' height='100%' fill='${bgcolor}'></rect> <circle cx='${cx}' cy='${cy}' r='10%' fill='${fill}'></circle> </svg-from-template> <svg-from-template bgcolor="lightgreen" cx="70" cy="70" fill="green"> <rect x='0' y='0' width='100%' height='100%' fill='${bgcolor}'></rect> <circle cx='${cx}' cy='${cy}' r='20%' fill='${fill}'></circle> </svg-from-template> <script> customElements.define( "svg-from-template", class extends HTMLElement { connectedCallback() { function parseTemplate(templateString, templateData = {}) { return new Function( // create Function AND return the executed function result "templateProps", [ "let f = ( " + Object.keys(templateData).join(",") + " ) =>", "`" + templateString + "`", "return f(...Object.values(templateProps))", ].join("\n") )(templateData); // execute tagged template function } setTimeout(() => { // wait till all innerHTML is parsed by the Browser let templateData = [...this.attributes].reduce((acc, attr) => { acc[attr.name] = attr.value; // copy element attributes to {} object return acc; }, { /*default object*/ bgcolor: 'pink', fill: 'red' }); let templateString = this.innerHTML; // OR read from file/server/universe this.innerHTML = "<svg mlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>" + parseTemplate(templateString, templateData) + "</svg>"; }); } } ); </script> <style> svg { width: 180px; /* SO snippet window height */ } </style>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM