FontAwesome Unicode in Plotly JS Scatterplot

I’m back on the war path of trying to find a way to get Font Awesome icons to show up in a javascript plotly scatterplot. I originally abandoned the idea and pursued using an image of the icon (here: Plotly Scatterplot Image. However, my biggest issue with that solution is that the image size is scaled to the x-axis. This means the size of the image is different depending on your zoom level. Instead, I would like it to be the same size regardless of x-axis range or zoom level.

I have reason to believe using FA unicode text is possible. I found this Python solution: Pictograms with Plotly and Font Awesome. Code below:

import pandas as pd
import plotly
import plotly.graph_objs as go
plotly.offline.init_notebook_mode()

title = 'Team scores'

ds = pd.Series({'Alpha' : 67, 'Bravo' : 30, 'Charlie' : 20, 'Delta': 12, 'Echo': 23, 'Foxtrot': 56})


Xlim = 16
Ylim = 13
Xpos = 0
Ypos = 12 ##change to zero for upwards
series = []
for name, count in ds.iteritems():
x = []
y = []
for j in range(0, count):
if Xpos == Xlim:
Xpos = 0
Ypos -= 1
x.append(Xpos)
y.append(Ypos)
Xpos += 1
trace = go.Scatter(x=x,
y=y,
mode="text",
text='\uf11b',
textposition="middle center",
textfont={"family": "FontAwesome",
"size": 18,
},
name=f'{name} ({count})',
hovertemplate=f'{name} ({count})',
)
series.append(trace)

fig = go.Figure(dict(data=series, layout=go.Layout(
title={'text': title, 'x': 0.5, 'xanchor': 'center'},
paper_bgcolor='rgba(255,255,255,1)',
plot_bgcolor='rgba(0,0,0,0)',
xaxis=dict(showgrid=False,zeroline= False, showline=False, visible=False, showticklabels=False),
yaxis=dict(showgrid=False,zeroline= False, showline=False, visible=False, showticklabels=False),
)))
fig.show()

I’d like to do the same. My environment is a react app, and not having luck. I imported css and webfonts folders into my assets and imported css into the test page:

import "assets/css/fontawesome.min.css";

Note - not using fontawesome-react as the method will not be creating a component. I’ll need the webfonts and css.

Trying to copy the Python approach, a trace is added to the plot that is mode='text'. Also, I checked the css file, and font-family is defined as "Font Awesome Pro 6". Here is my attempt:

  let trace = {
    x: noteDates,
    y: new Array(noteDates.length).fill(1),
    mode: "text",
    hovertemplate: "Date: %{x}<extra></extra>",
    text: "\uf11b",
    textposition: "middle-center",
    textfont: {
      family: "Font Awesome 6 Pro",
      size: 20,
      weight: 900,
    },
    name: "Note",
    yaxis: "y2",
    showlegend: false,
  };

Unfortunately, this does not work. But, i have reason for hope again from the Python example - they seemingly had success. Also, I found the method to work somewhat, if it is not Font Awesome unicode. For instance, if I alter the code to this:

  let trace = {
    x: noteDates,
    y: new Array(noteDates.length).fill(1),
    mode: "text",
    //hoverinfo: "none",
    hovertemplate: "Date: %{x}<extra></extra>",
    text: "&#x1f4c4;",
    textposition: "middle-center",
    textfont: {
      size: 20,
      weight: 900,
    },
    name: "Note",
    yaxis: "y2",
    showlegend: false,
  };

… then I do see the character. Here is a list of icon type standard? unicode hex characters: Unicode Characters List. Many of them do work. Certainly, perhaps with some settings adjustments? the Font Awesome characters can work?

For testing / reference, here is a list of Font Awesome unicode characters from v5: Font Awesome Cheatsheet

Thanks for any help!

1 Like

Two small things make this work.

  1. Importing the correct css file (all.min.css rather than fontawesome.min.css)
  2. Use family: "FontAwesome"

It seems many, but not all work. Could be related to #2 above. Would be nice to have access to sharp, duotone, etc. They appear to render bold and maybe lack some clarity. I actually think the regular unicode emoji’s might look the best for the way I’m using them. And doesn’t require importing more code.

At any rate- hope it helps someone, and would be interested to see if anyone gets any of the others working (thin, sharp, duotone) and better luck with clarity.

2 Likes

@allsyntax your post was really useful to me, since you seem to be the only one on the interwebs to get this to work. I was able to find a way, too, thanks to your post, but the syntax for me was slightly different. To help anyone else who lands here and has trouble, I’ll post my solution. I’m using Angular with Plotly.js, and I need to have comments in a plot. So I choose to use the FontAwesome info-circle icon, with different colors and sizes based on whether the comment is “new” or not.

I have a list of comments, so this is iterative. The comments need to be clickable, with behaviour to show the comment and log it as “seen”. The icons for comments that have been seen are smaller and a lighter color than the “new” comments. The comments are associated with various points on the plot, with datetime along the x axis and values along Y.

I’m able to build my annotations, and get the icons I want, by this syntax:

let annotation = {
      yref: 'paper',
      x: comment.plot_timestamp,
      y: .85,  //we like it to show in the top part of the graph, we have a toggle to turn them off if they get in the way 
      mode: "text",
      text: "&#xf05a;"; //This is a fontawesome unicode symbol for a circle with an "i" in it. "\uf05a" didnt work when deployed.
      font: {
        family: "'Font Awesome 5 Free'", //Note the quotes!
        weight: 900, //this doesnt have any effect, so we will style this in a global style css see below
        size: iconSize,
        color: lineAndIconColor, //there is an associated line defined in shapes, but that part is pretty standard
      },
      hovertext: "Show comment",
      captureevents: true, //this allows us to use the OnClickAnnotation(event: any) event listener in the plot component
      showarrow: false,  //we like a plain line from the comment down to the x axis
      //stuff commentId in this custom property, to be used if the user clicks the annotation
      commentId: comment.id,  //inside our event listener, we can access this custom attribute
    }
    annotations.push(annotation);

The css we need for the font-weight is here. Since we are using angular, we must put this in a global style to get around the Angluar css style encapsulation that happens when you try to style another component from other.

/*Note: the $= below means any text ENDING WITH the given characters.
  We use this to avoid styling every annotation text.  This will apply only to the info-circles for comments
  The font-weight 900 is simply required in order for the fontawesome unicode symbol to be viewable.  And there is no
  way to add it via a regular plotly config variable.  Hence, we have to add it here in css global styling */
.annotation-text[data-unformatted$="f05a;"] {
  font-weight: 900;
}

Hope this helps somebody, paying it forward / back.

image

1 Like

Thanks! I’m going to review what you published in more detail when I get a chance. I’m glad you got it to work and that this thread served as some help at least.

I applied a mouse over on mine with the date - and serve that as props to a react carousel that has all of the notes, and use effect on the date prop, will navigate to and highlight the note user mouse over. — a lot like Google finance.

1 Like