-1

I'm building an editor where users can select an SVG from our CDN, and select its fill color. On the front-end I want to be able to render these SVG's in the color that's picked by the user, but this doesn't seem to be possible. Does anybody know any approaches I should try?

The data I get from the server is the following:

  • cdnURL: the URL from which the SVG should be loaded

  • fillColor: text corresponding to SCSS variables in our frontend. I have made utility classes for all colors to implement the fill-property:

    color__fill--black { fill: black; }
    

I have come across answers on this site that suggest changing the fill-property of the SVG-file, but this is not possible because I only have its source-URL on the CDN. I have also seen people suggest using CSS filters, but this does not solve my issue as the colors vary a lot, from black to blue to yellow to white.

Sandeyez
  • 49
  • 3
  • Are you trying to do something like a paint-by-number or just trying to fill in the background? – computercarguy Jan 20 '23 at 17:15
  • create a div position absolute, at -10000px, embed the svg code in this div. Now you have an embed you can work on. Change fill color, or anything else. Copy this div content (svg) on screen where you want to have it. – pier farrugia Jan 20 '23 at 17:52
  • 1
    See https://stackoverflow.com/questions/11978995/how-to-change-color-of-svg-image-using-css-jquery-svg-image-replacement – Robert Longson Jan 20 '23 at 21:27

2 Answers2

0

I will suggest that you load the selected SVG and insert it inline into an HTML element. Here I just use the fetch function. Basically my data URLs in the array could be replaced with ordinary URLs and the code will still work (running from a web server from the same domain).

There could be a number of different approaches to when it comes to the color. Here I change the content of a style element. Any element in the SVG will get the specified color.

const urls = [ 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTSA1IDAgTCAwIDUgTCA1IDEwIEwgMTAgNSBaIiAvPgo8L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIC8+Cjwvc3ZnPg=='
];

const container = document.getElementById('container');
const style = document.getElementById('style01');

document.forms.form01.img.addEventListener('change', e => {
  if(e.target.value){
    fetch(urls[e.target.value]).then(res => res.text()).then(text => {
      container.innerHTML = text;
    });
  }
});

document.forms.form01.color.addEventListener('change', e => {
  style.textContent = `#container * {fill: ${e.target.value};}`;
});
#container {
  width: 200px;
}
<style id="style01">#container * {fill: #1a5fb4;}</style>
<form name="form01">
  <select name="img">
    <option>Select an SVG</option>
    <option value="0">SVG 1</option>
    <option value="1">SVG 2</option>
  </select>
  <input name="color" type="color" value="#1a5fb4" />
</form>
<div id="container"></div>
chrwahl
  • 8,675
  • 2
  • 20
  • 30
0

Easy does it, create a native javascript <load-svg> Web Component.

  • loads external SVG files
  • assigns its to a shadowDOM innerHTML
  • appends all your <style> elements

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px  } path:nth-child(2n+2) { fill: red }
  </style>
</load-svg>

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px } path:nth-child(3n+2) { fill: yellow }
  </style>
</load-svg>

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px } path:nth-child(3n+1) { fill: blue }
  </style>
</load-svg>

<script>
  customElements.define('load-svg', class extends HTMLElement {
    async connectedCallback() {
      this.attachShadow({mode:"open"})
          .innerHTML = await (await fetch(this.getAttribute("src"))).text();
      this.shadowRoot.append(...this.childNodes);
    }
  });
</script>
Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49