I'm creating a svg icon to fill with a color percentage from linearGradient.
In linearGradient I'm creating id's dynamically and want to make use of the same dynamically created id's in
I tried interpolation fill={url(#linear${i}
)} which didn't work and not sure if this is the right way to use in SVG.
Is there a better way to achieve this?
<div *ngFor="let block of filteredBlocks; let i = index">
<svg xmlns="http://www.w3.org/2000/svg"
height="100px"
viewBox="0 0 24 24"
width="100px"
fill="url(#'linear' i)">
<defs>
<linearGradient [attr.id]="'linear' i">
<stop [attr.offset]="block.percent '%'" stop-color="green"/>
<stop [attr.offset]="(100 - block.percent) '%'" stop-color="white"/>
</linearGradient>
</defs>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M17 4h3v16h-3V4zM5 14h3v6H5v-6zm6-5h3v11h-3V9z" />
</svg>
</div>
CodePudding user response:
There are different ways to make it working:
use interpolation on attribute binding
attr.fill="url(#linear{{i}})"
use string concatentation on attribute binding
[attr.fill]="'url(#linear' i ')'"
CodePudding user response:
Wrap it in a native JS Web Component, supported in all modern browsers,
no unique ID required if you use shadowDOM
If you don't want shadowDOM, stick on
new Date()/1
to force a new unique ID
customElements.define("svg-icon",class extends HTMLElement{
connectedCallback(){
let offset = this.getAttribute("offset") || 5;
let color = this.getAttribute("color") || "green";
let id = "gradient"; // (new Date()/1)
this
.attachShadow({mode:"open"}) // leave out for no shadowDOM
.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
height="100px" width="100px"
fill="url(#${id})">
<defs>
<linearGradient id="${id}">
<stop offset="${offset}%" stop-color="${color}"/>
<stop offset="${100 - offset}%" stop-color="white"/>
</linearGradient>
</defs>
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M17 4h3v16h-3V4zM5 14h3v6H5v-6zm6-5h3v11h-3V9z"/>
</svg>`
}
});
<svg-icon></svg-icon>
<svg-icon offset="20"></svg-icon>
<svg-icon color="red"></svg-icon>