I have an ongoing problem with custom webfonts and fabric.js. My app uses a lot of custom webfonts and I init them when adding an iText to my canvas:
var text = new fabric.IText("My Text", {
fontFamily: "Some Custom Font Family",
fontSize: 50,
top: 0,
left: 0,
fill: "#000000"
});
canvas.add(text);
canvas.bringToFront(text);
canvas.setActiveObject(text);
canvas.renderAll();
That works but only if I click on the iText on my canvas and interact with it. Then, once the font has loaded, its not a problem anymore. The problem is initially and the first time the iText is added.
I researched a lot and came to this thread:
Init loaded text with remote web font in Fabric.js
but that didn't help me. The jsfiddle provided there has the exact same problem:
http://jsfiddle.net/vvL6f/6/
Just open this fiddle with a fresh browser (e.g. Chrome CMD+Shift+R) with cleared cache. You will see once you open the fiddle, the custom webfont is not loaded but immediately loads when you click on the iText on the right.
Now, how can we solve this?
A suggested approach was to set useNative
to false and let Cufon render the text, but that didn't work.
I load my webfonts in a CSS file like this:
@font-face {
font-family: 'ApolloASM';
src: url('ApolloASM-webfont.eot');
src: url('ApolloASM-webfont.eot?#iefix') format('embedded-opentype'),
url('ApolloASM-webfont.woff2') format('woff2'),
url('ApolloASM-webfont.woff') format('woff'),
url('ApolloASM-webfont.ttf') format('truetype'),
url('ApolloASM-webfont.svg#apollo_asmregular') format('svg');
font-weight: normal;
font-style: normal;
}
@Prominic answer is almost there. I also have a canvas app which uses custom fonts with Fabric. I load all fonts in a CSS just as you do. The catch is, only declaring the @font-face
in your stylesheet is not enough. The browser won't request the font file unless it is used in the document. And you have to be sure to load and apply the webfont before initializing the canvas. This can be achievable with a little bit of work, which I'll illustrate with an example below. The downside is that you might need to preload all fonts that your app make available to your users.
@font-face
statement in a stylesheet. Just make sure it is loaded in the <head>
section. Let's use your example: @font-face {
font-family: 'ApolloASM';
src: url('ApolloASM-webfont.eot');
src: url('ApolloASM-webfont.eot?#iefix') format('embedded-opentype'),
url('ApolloASM-webfont.woff2') format('woff2'),
url('ApolloASM-webfont.woff') format('woff'),
url('ApolloASM-webfont.ttf') format('truetype'),
url('ApolloASM-webfont.svg#apollo_asmregular') format('svg');
font-weight: normal;
font-style: normal;
}
Bonus Tip: If you use italic and/or bold in your app, is adviseable to add the font-faces for those styles as weel if you want consistent results across different browsers. For example, Android Browser 4.2 can't compute italic of a font, and will display it as normal.
As I said above, you will need to actually use the font in the DOM to force the font to load. Just adding a div with some text and styling it with your font will be enough:
<div style="font-family:'ApolloASM'"> </div>
Bonus Tip: Don't forget to add the italic and bold variations as well
load
eventYou will need to sync the canvas init (or at least the text addition) after the font is loaded by the browser, or else you might see a FOUT effect (Flash of Unstyled Text). Luckily for us, the browser won't fire the load
event until all font files are loaded, which can be used to safely add a styled text to canvas:
window.addEventListener('load', function onLoad() {
var canvas = new Fabric.Canvas({...});
var text = new fabric.Text("Web Font Example", {
left: 200,
top: 30,
fontFamily: 'ApolloASM',
fill: '#000',
fontSize: 60
});
canvas.add(text);
canvas.renderAll();
})
Bonus Tip: You can wrap those fonts <div>
's in another one and remove it after the DOM load
event, to avoid breaking any layout you might have.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With