6

I want to render a FontAwesome icon as an SVG dynamically provide it as an image source using Javascript. I want my output to be something like this

output

PS - I will draw the circle myself. Just need a way to render the icon.

So far, I have tried this approach:

function addSVG() {

  var ele = document.getElementById("svg");

  var svg = `<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
        <text x="4" y="15" style="font-family: FontAwesome" fill="red">&#xf007;</text>
    </svg>`

  var output = 'data:image/svg+xml;base64,' + btoa(svg)

  ele.src = output;
}
addSVG()
<head>
  <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet">
</head>

<body>
What it should look like:
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
    <text x="4" y="15" style="font-family: FontAwesome" fill="red">&#xf007;</text>
  </svg>
What it looks like:
  <img id="svg">
</body>

As you can see, without the Javascript (just using SVG in HTML) it works fine.

Frame91
  • 3,457
  • 6
  • 43
  • 88
Janit Mehta
  • 165
  • 1
  • 9
  • Which version of Font Awesome (looks like 4.4, from the CDN reference)? Have you reviewed this already? https://fontawesome.com/how-to-use/on-the-web/setup/getting-started?using=svg-with-js – Tieson T. Jul 05 '18 at 19:29
  • Yes, the question of which version of Font Awesome would make a big difference on the answer. Font Awesome 5 has built in methods of rendering SVG icons, so the approach in v5 may be very different than if you were limited to v4. And I would wonder whether it's necessary to implement it as an or if your ultimate goal is simply to get the outcome of an svg icon over a background circle. If the latter, then there are much more straightforward approaches in v5. – mwilkerson Jul 06 '18 at 04:04

3 Answers3

4

Why do you need it in img tag? SVG is an image! You do not need it to put in something else.

May be I do not know something from you, but I think this is just a bad idea from you.

My suggestion: put SVG in HTML with font-awesome icons directly:

Your benefit from this: all modern browsers support it without any limits like in img tags or as background image.

var divSvg = document.getElementById('svg'),
    pics =
    {
        user: {col: '00a', icon: 'f007'},
        home: {col: '08c', icon: 'f015'},
        folder: {col: '88f', icon: 'f07c'},
        gear: {col: '5a0', icon: 'f013'},
        flag: {col: '05a', icon: 'f024'},
        leaf: {col: '080', icon: 'f06c'}
    },
    svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">\
    <text x="4" y="24" fill="COLOR" style="font:24px FontAwesome;cursor:pointer">PIC</text>\
</svg>';

for(var title in pics)
{
    var newSVG = svg.replace('PIC', '&#x'+pics[title].icon+';');
    //we put it in "B" tag to have a title because IE
    //does not support title attribute and title tag in SVG
    divSvg.innerHTML += '<b title="' + title + '">' +
                    newSVG.replace('COLOR', '#'+pics[title].col) + '</b>';
}

divSvg.onclick = function(e)
{
    if(e.target.tagName == 'text')
    {
        document.getElementById('output').innerHTML = 'Was clicked on ' +
                                // we take title from "B" tag:
                                e.target.parentNode.parentNode.title;

        /* if you need you can use:
        switch(e.target.parentNode.parentNode.title)
        {
            case 'user': alert('Here some procedure with user');
            case ...     YOUR CODE
            and so on... YOUR CODE
        }*/
    }
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet">
<div id="svg"></div><br>
<div id="output">Please click on any icon.</div>
Bharata
  • 12,657
  • 6
  • 32
  • 48
  • The downside of embedding SVG directly in HTML is that you have to serve the content of the entire page as XHTML in order to be compatible, which has slightly different and more strict semantics than HTML, which might break other parts of the page if tags aren't explicitly closed, etc. – Patrick Roberts Jul 06 '18 at 13:54
  • @Bharata Interesting and helpful answer for me – Alexandr_TT Sep 06 '20 at 07:13
3

You can't use an <img> element when referencing an external CSS stylesheet from XML. You need to use an <object> element like this answer recommends, and prepend an <?xml-stylesheet?> processing instruction in order for the SVG+XML blob to be able to find the FontAwesome glyph for the HTML entity &#xf007;.

function addSVG() {
  var ele = document.getElementById("svg");
  var svg = `
    <?xml-stylesheet type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"?>
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
        <text x="4" y="15" style="font-family: FontAwesome" fill="red">&#xf007;</text>
    </svg>`
  var output = `data:image/svg+xml;utf8,${svg}`

  ele.type = 'image/svg+xml';
  ele.data = output;
}
addSVG()
<head>
  <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet">
</head>

<body>
  What it should look like:
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
    <text x="4" y="15" style="font-family: FontAwesome" fill="red">&#xf007;</text>
  </svg> What it looks like:
  <object id="svg"></object>
</body>
Patrick Roberts
  • 44,815
  • 8
  • 87
  • 134
0

You don't need to convert the data into base64. I think the SVG syntax doesn't have any "crazy" characters in it, so it's safe to use.

Set the encoding to UTF-8, and drop the <svg> in there:

'data:image/svg+xml;utf8,<svg ... > ... </svg>'