Adding FontAwesome icons to a D3 graph

Javascriptd3.jsFont Awesome

Javascript Problem Overview


I am trying to set an icon with FontAwesome instead of text in my D3 nodes. This is the original implmentation, with text:

g.append('svg:text')
    .attr('x', 0)
    .attr('y', 4)
    .attr('class', 'id')
    .text(function(d) { return d.label; });

And now I try with icons:

g.append('svg:i')
   .attr('x', 0)
   .attr('y', 4)
   .attr('class', 'id icon-fixed-width icon-user');

But this is not working, even though the markup is right, and the CSS rules are properly hit: the icons are not visible.

Any idea why?

Here is the related jsbin

EDIT

I have found this alternative to insert images: http://bl.ocks.org/mbostock/950642

node.append("image")
    .attr("xlink:href", "https://github.com/favicon.ico")
    .attr("x", -8)
    .attr("y", -8)
    .attr("width", 16)
    .attr("height", 16);

Which is exactly what I want to do, but it does not work with <i> elements used by FontAwesome.

Javascript Solutions


Solution 1 - Javascript

You need to use the proper Unicode inside a normal text element, and then set the font-family to "FontAwesome" like this:

 node.append('text')
    .attr('font-family', 'FontAwesome')
    .attr('font-size', function(d) { return d.size+'em'} )
    .text(function(d) { return '\uf118' }); 

This exact code will render an "icon-smile" icon. The unicodes for all FontAwesome icons can be found here:

http://fortawesome.github.io/Font-Awesome/cheatsheet/

Be aware that you need to adapt the codes in the cheatsheet from HTML/CSS unicode format to Javascript unicode format so that &#xf118; must be written \uf118 in your javascript.

Solution 2 - Javascript

Thanks to all that replied. My final solution is based on the answer by CarlesAndres:

g.append('text')
    .attr('text-anchor', 'middle')
    .attr('dominant-baseline', 'central')
    .attr('font-family', 'FontAwesome')
    .attr('font-size', '20px')
    .text(function(d) { return ICON_UNICODE[d.nodeType]; });

Be careful with your CSS: it takes precedence over the SVG attributes.

And this is the way it looks:

Node Graph

The good thing about this, compared to the foreignObject solution, is that events are properly handled by D3.

Solution 3 - Javascript

I'm truly new to d3, but font awesome works by styling an <i> element with a class attribute.

The only way I found is to append a foreignObject and set on it the relevant HTML needed by font awesome.

Reference:

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject?redirectlocale=en-US&redirectslug=SVG%2FElement%2FforeignObject

http://fortawesome.github.io/Font-Awesome/examples/

Code:

g.append('svg:foreignObject')
    .attr("width", 100)
    .attr("height", 100)
    .append("xhtml:body")
    .html('<i class="icon-fixed-width icon-user"></i>');

Demo: http://jsbin.com/eFAZABe/3/

Solution 4 - Javascript

Given that the other answers don't work anymore (because d3js has been updated in the meanwhile) and because it's not a good solution to use svg:foreignObject due to compatability issues, here is an answer that works without having to use any hacks:

.append("text")      // Append a text element
.attr("class", "fa") // Give it the font-awesome class
.text("\uf005");     // Specify your icon in unicode (https://fontawesome.com/cheatsheet)

Here is a working example (click "Run code snippet" and the d3 code outputs three stars):

var icons = [1, 2, 3];

d3.select("body")
  .selectAll(".text")
  .data(icons)
  .enter()
  .append("text")       // Append a text element
  .attr("class", "fa")  // Give it the font-awesome class
  .text("\uf005");      // Specify your icon in unicode

<link href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Solution 5 - Javascript

I know this question is old, been resolved, but - this worked for me today.

From this site

svg.append('svg:foreignObject')
    .attr("width", 50)
    .attr("height", 50)
    .append("xhtml:body")
    .html('<i class="fa fa-user"></i>');

But for my chart, I dropped the append xhtml:body, otherwise it wouldn't let me set x and y coords.

The element will adopt the width and height of the font you set.

d3.select('svg')
	.append('svg:foreignObject')
	.attr('class', 'handle')
	.attr('x',  +getLeftBarPosition(i+1, 'handle')[0] + +getLeftBarPosition(i+1, 'handle')[1])
	.attr('y', state.barHeight/2)
	.html('<i class="fa fa-user"></i>')

Solution 6 - Javascript

Just to put in code here what worked for me based on CarlesAndres's answer and mhd's comment:

node.append("text")
    .attr("style","font-family:FontAwesome;")
    .attr('font-size', "50px" )
    .attr("x", 440)
    .attr("y", 440)
    .text(function(d) { return '\uf118' });

Solution 7 - Javascript

Font awesome 4.x versions are not supporting if we use as follows

svg.append('text')
   .attr('x', 15)
   .attr('y', -17)
   .attr('fill', 'black')
   .attr('font-family', 'FontAwesome')
   .attr('font-size', function (d) { return '20px' })
   .text(function (d) { return '\uf2b9' });

so replace this

.attr('font-family', 'FontAwesome')

with

.attr("class", "fa")

Hope it helps for FA 4.x

Solution 8 - Javascript

For those who banging their head hard. D3 - 6.2.0 and FontAwesome - 5.13.0 Below worked

nodeEnter.append('text')
	.attr('width', "10px" ).attr('height', "10px" ) // this will set the height and width
	.attr("class","fas fa-adjust") // Font Awesome class, any
	.attr("x", 15) // for placement on x axis
	.attr("y",-5); // for placement on y axis

Solution 9 - Javascript

For those who want to use svg icons from FontAwesome with D3, this snippet should work:

btnGroup.append("g")
  .attr("width", 16)
  .attr("height", 16)
  .attr("class", "fas fa-check-square");

The only drawback here is that width and height are not inherited from CSS. The good news is that class toggling works as expected with d3 and jquery.

Demo with toggling on click: https://jsfiddle.net/diafour/6fagxpt0/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionblueFastView Question on Stackoverflow
Solution 1 - JavascriptCarles AndresView Answer on Stackoverflow
Solution 2 - JavascriptblueFastView Answer on Stackoverflow
Solution 3 - JavascriptIrvin DomininView Answer on Stackoverflow
Solution 4 - JavascriptJean-PaulView Answer on Stackoverflow
Solution 5 - JavascriptJasTonAChairView Answer on Stackoverflow
Solution 6 - JavascriptJasonView Answer on Stackoverflow
Solution 7 - JavascriptNavinView Answer on Stackoverflow
Solution 8 - JavascriptAadamView Answer on Stackoverflow
Solution 9 - JavascriptdiafourView Answer on Stackoverflow