4

I need to load, display and dynamically change the color of an SVG image in my Angular project by applying different CSS classes to it.

This question didn't help, since it makes use of the Modernizr library and I would like to avoid it. I don't want also to copy the d field in the path tag of the image I have directly in the html file of the Angular project because it would be a wall of text that I'm not willing to accept. I can accept instead the usage of an external dedicated library to achieve the correct outcome, like the ng-inline-svg, which I tried to use the following way:

<div class="svg1" aria-label="My icon"
   [inlineSVG]="'./assets/images/icons/ApplyIcon.svg'">
</div>

Defying the following CSS class:

.svg1 {
  color: green;
}

It loads the image perfectly as a regular img tag but if I try then to apply a custom class to it to change the image color, it doesn't work.

Furthermore, I tried to use the object tag the following way:

<div class="col-2">
    <object
       id="svg1"
       data="./assets/images/icons/ApplyIcon.svg"
       type="image/svg+xml">
    </object>
</div>

But, again, if I apply a class to the object tag with the CSS directives color: green; or fill: green; nothing would change. Any idea to achieve what I want?

Rexam
  • 823
  • 4
  • 23
  • 42

7 Answers7

2

Use the svg element in component.html file and use [ngClass] directive to dynamically change the inner svg class based on the conditions.

example:

component.ts

data.state = "New" || "In-Progress" || "Completed" // this changes dynamically based on the data

component.html:

<svg <circle class="cls-3" [ngClass] = "{'New': 'blue', 'In-Progress':'orange','Completed':'green'}[data.state]" cx="8.21" cy="8.01" r="2.44" transform="translate(-3.22 8.89) rotate(-48.73)"/></svg> // inner class of svg element

component.css:

.blue {
    fill:blue
}
.orange{
   fill: orange
}
.green {
   fill: green
}
Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
1

I tried different ways to change img src SVG colors finally achieved using SVG as a mask and It's working as expected for me.

Angular HTML:

 <div class="icon" [ngStyle]="{'mask': 'url(' + icon + ') no-repeat center', '-webkit-mask': 'url(' + icon + ') no-repeat center'}"></div> 

Angular CSS

 .icon {
    background-color: #0000; // Here you can the svg color
  }
Raja Rama Mohan Thavalam
  • 8,131
  • 2
  • 31
  • 30
1

In my case, I need to change the color of few paths and circle inside whole SVG element.

This fixed my problem: <svg>... <path [attr.fill] = "<color>" ... /> ...</svg>.

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
0

Use the setAttribute() property to change the color of the SVG,

document.getElementById("svg1").setAttribute("fill", "green");
Angela Amarapala
  • 1,002
  • 10
  • 26
  • 1
    Applying directly `style="fill: green;"` to the `object` tag doesn't work, as I explained in my question, so why should this work? Furthermore, in Angular projects we should avoid accessing the DOM directly like you're doing here because that's Angular’s sphere of control. – Rexam Dec 12 '19 at 09:58
0
fill: green;

works only for path element which is usually present in svg element. color property is for font color and it won't work on svg element. In your scenario you can below things 1) in your folder /assets/images/icons/ApplyIcon.svg edit svg icon and for that path give attribute fill="green" 2) If you want to use that icon on multiple places with different color then above method will not work because same color will get applied everywhere. In this case you can simply remove fill="color" from all path inside svg. and after this you can apply css

fill:color;

In this case although fill:color is not applied on SVG it will traverse to child element path and hence it will work.

Santosh Kadam
  • 1,265
  • 14
  • 14
  • I noticed that the `fill: green` is correctly applied for the `path` element, but unfortunately your solution (1) doesn't work for me because I need to change that image color according to a status and I really would avoid solution (2) because I see it as an unnecessary overload. Isn't there really no other way to apply a `fill` property to a SVG image in Angular? Or rather, to load an SVG image as an icon maybe and change its color by applying a CSS class? – Rexam Dec 12 '19 at 10:22
  • simply add inline svg icon instead of giving path of scg icon. now in path of svg you can dynamically change fill attribute based on your status. – Santosh Kadam Dec 12 '19 at 10:32
  • Could you elaborate it more and/or provide an example, please? – Rexam Dec 12 '19 at 10:37
  • added that in answer – Santosh Kadam Dec 12 '19 at 10:52
  • In question you have mentioned that you don't want to put lengthy svg element in template so I think I approach will not work. I think without that you will not able to access path element as it create another embedded document element. – Santosh Kadam Dec 12 '19 at 11:14
0

I recently faced this same issue and resolved it by generating a new Angular component and using my .svg file in place the the component's .html file.

For instance, updating the template path to point to your .svg, like this: templateUrl: './my-icon.component.svg'. You can then add Angular directives inside the SVG file.

Check out this example: https://levelup.gitconnected.com/using-svg-files-as-component-templates-with-angular-cli-ea58fe79b6c1

Thomas B
  • 51
  • 8
0

The accepted answer is good but then what if you have a bloated SVG?

we first need to transform the SVG or all SVG in the project using @ngneat/svg-icon

if the fill or stroke properties of elements in the SVG are set to currentColor, they will have the color defined for the containing DOM element,. So the color can easily be changed by changing the color style on the svg-icon element.

move your SVGs icons to src/assets/svg directory the run ng add @ngneat/svg-icon

this command installs the svg-icon to your project and automatically generates the svgs into ts files where the svgs are turned to objects containing

  • the name key : this is the generated name for the svg and will be used to identify the svg
  • the data key: this is essentially the svg code copied from the svg files

the generated svg can be found on the app/svg directory

looking at the app.module.ts file the SvgIconsModule is imported and it is declared in the @Ngmodule imports.

import all the svg you want to use in the project from the app/svg directory and put it in the array of icons exposed by the SvgIconsModule.

import { SvgIconsModule } from '@ngneat/svg-icon';
import { appMasterCardLogoIcon, appPaypalLogoIcon, appVisaLogoIcon } from './svg';

@NgModule({
  ...,
  imports: [
    BrowserModule,
    SvgIconsModule.forRoot({
      icons: [appApplePayLogoIcon,
        appMasterCardLogoIcon,
        appPaypalLogoIcon,
        appVisaLogoIcon],
    })
  ],
 ...
})

you can now use the svg-icon tag anywhere in your component, then the attribute key will be the generated name key (used in identifying the svg)

because the fill or stroke property is set to currentColor, we can then use the color attribute on the svg-icon to control the color

we can also add a class to the svg-icon tag and control the styling using ng-class

<svg-icon key={{payment.logoKey}} [ngClass]="{'selected-payment': payment.isSelected}"class="payment-logo"></svg-icon>
Justice Otuya
  • 11
  • 1
  • 3