Why does this technique for using fontawsome 5 in text on a canvas fail for icon fa-plug when it works for fa-amazon?

35 views Asked by At

This is about using Fontawesome icons in text on a html5 canvas. Why will the technique NOT work with the fa-plug icon when it does work with the fa-amazon icon.

The code is in the snippet below but it seems to have async issue in the snippet editor, so it is also in a Codepen over here where it is more reliable. The async part relates to the download of fontawesome into the page which is slower in these online code editors. There is a 1 sec timeout to delay the main code for that purpose.

The answer to this other question shows how to use FA icons in text on a plain HTML5 canvas. I modified that to make the snippet below which uses the Konva lib as a wrapper for the HTML5 canvas.

The technique used is to add an element to the DOM, set the FA class info, then read back from the computed styles to get the font name and weight which are critical to get the text to pick up the FA font.

I can get this to work with 'some' FA icons but not, specifically, the plug.

Look at the lines

const className = 'fab fa-amazon' 
// const className =  'fas fa-plug'

Try with the fa-amazon className and you will see we get the element AND the same icon appears on the canvas. FA docs for fa-amazon here.

But try with the fa-plug class and we only get the element but the plug does NOT appear in the canvas. FA docs for fa-plug here.

I think it is something to do with the final step of getting the character via

String.fromCodePoint(iBeforeStyles.getPropertyValue('content').codePointAt(1)),

I believe the decimal value for the plug icon in FA is outside of the usual Unicode range - I think Unicode calls it a 'private' glyph. My hunch is that because there is no unicode representation, the String.fromCodePoint() throws out something unusable.

Anyone got any ideas?

const stage = new Konva.Stage({
  container: 'container',
  width: 300,
  height: 200
})
const layer = new Konva.Layer()
stage.add(layer)

setTimeout(start, 1000)

function start() {
// Now the interesting part. We put an <i> on the page then set its class
// to pull in the FA style, and interogate the element's computed styles
// to get the font settings and character.

// create an icon with the Font Awesome class name you want
const i = document.createElement('i');
//i.style.display = 'none' // do not hide for time being

const className = 'fab fa-amazon' 
// const className =  'fas fa-plug'
i.setAttribute('class', className);
document.body.appendChild(i);

// get the styles for the icon you just made
const iStyles = window.getComputedStyle(i);
const iBeforeStyles = window.getComputedStyle(i, ':before');

// Pull out the interesting parts - we need these to ensure that we have 
// the correct font engaged in the konva text shape. 
const fontFamily = iStyles.getPropertyValue('font-family');
const fontWeight = iStyles.getPropertyValue('font-weight');
  
// Now apply the stuff we got above

const text = new Konva.Text({
  x: 0,
  y: 0,    
  width: 40,
  height: 40, 
  fill: 'black',
  fontSize: 12,
  fontFamily: fontFamily, 
  fontWeight: fontWeight,
  text: String.fromCodePoint(iBeforeStyles.getPropertyValue('content').codePointAt(1)),
  align: 'center',
  verticalAlign: 'middle'  
})
layer.add(text)

console.log(text.fontFamily())
}
body{ background-color: ivory; }

#container{border:1px solid red; margin:0 auto; }
<html>
<head>
  <script src="https://unpkg.com/konva@9/konva.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.css"  crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>

<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<h4>Font Awesome glyph drawn onto Konva canvas</h4> 


<div> <span class='icon'></span> </div>

<div id='container'></div>

</body>
</html>

0

There are 0 answers