Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Init loaded text with remote web font in Fabric.js

I'm working on a big custom application with Fabric JS and I already did a great job. But I have a problem with init loaded text object that uses a webfont.

As long as that font is local on the client's computer, I works fine, ELSE the webfont is NOT loaded and the text object on the canvas is rendered in a default sans-serif font-family.

Here is, in short, what I do (in this example I use "allstar" as my webfont):

CSS: The css is loaded inside fonts.css in the head before fabric.js

@font-face{
    font-family:'allstar';
    src:
        url('/path-to-fonts/all_star-webfont.eot');
    src:
        url('/path-to-fonts/all_star-webfont.eot?#iefix') format('embedded-opentype'),
        url('/path-to-fonts/all_star-webfont.woff') format('woff'),
        url('/path-to-fonts/all_star-webfont.ttf') format('truetype'),
        url('/path-to-fonts/all_star-webfont.svg#allstarregular') format('svg');
    font-weight:normal;
    font-style:normal
}

Javascript: this is loaded at the bottom of the page inside $(document).ready(function(){})

var textSample = new fabric.Text(text, {
    fontFamily: "allstar",
});
canvas.add(textSample);
canvas.renderAll();

If I use the font elsewhere on the page (e.g.: in a transparent span tag with a dot and the font loaded), it works fine. But I don't think that's a proper way to code.

I Use fabric.js version 1.3.0

like image 223
Jens Avatar asked Nov 12 '13 11:11

Jens


People also ask

How to load a font with JavaScript?

Rather than having every user load all 20 fonts, which is what would happen using the traditional CSS @font-face method, we can load a font with JavaScript only if a user requests it. The first step is to define a FontFace object for the font. Pass on two parameters, the first being the a name and the second being the path to the font.

What is the use of fontfamily property in fabric JS?

fontFamily : It specifies the font-family. Below is the example that illustrates the use of fontFamily property in Fabric.js: ide.geeksforgeeks.org , generate link and share the link here.

What is CSS font loading API and how to use it?

The CSS Font Loading API lets you load fonts dynamically with JavaScript only if and when you need them. Let’s say we’re building a little editor where the user can pick from 20 different fonts for their text.

Can I use custom fonts on a fabric canvas?

/* When working with custom fonts on a fabric canvas, it is recommended to use a font preloader. Not doing so is likely to cause texts that are imported onto the canvas to be rendered with a wrong (default) font. It can also cause you to see a FOUT (Flash of Unstyled Text) right after changing the font of a text.


4 Answers

The issue:

  1. Canvas renders immediately
  2. Google loads webfonts
  3. Canvas has no idea until the next event that re renders it

The solution:

  1. Canvas renders immediately
  2. Google loads webfonts with a callback
  3. You force render
  4. Canvas now has the

http://jsfiddle.net/vvL6f/6/

WebFontConfig = {
    google: { families: [ 'Ribeye::latin', 'Lora::latin', 'Croissant+One::latin', 'Emblema+One::latin', 'Graduate::latin', 'Hammersmith+One::latin', 'Oswald::latin', 'Oxygen::latin', 'Krona+One::latin', 'Indie+Flower::latin', 'Courgette::latin', 'Ranchers::latin' ] }
};

(function() {
    var src = ('https:' === document.location.protocol ? 'https' : 'http') +
        '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';

    $.getScript(src, function(data) {      
        // Not sure why I need to run this twice but it makes it load the font and then reposition the font to it's correct coords.
        canvas.renderAll();
        canvas.renderAll();
    });
})();
like image 112
Michael J. Calkins Avatar answered Oct 28 '22 18:10

Michael J. Calkins


Short way:

<script src="//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js"></script>
<script>
WebFont.load({
            google: {
                families: [ 'Abel', 'Aclonica']
            },
            fontinactive: function(familyName, fvd) {
                console.log("Sorry " + familyName + " font family can't be loaded at the moment. Retry later.");
            },
            active: function() {
                // do some stuff with font   
                $('#stuff').attr('style', "font-family:'Abel'");
                var text = new fabric.Text("Text Here", {
                    left: 200,
                    top: 30,
                    fontFamily: 'Abel',
                    fill: '#000',
                    fontSize: 60
                });

                canvas.add(text);
            }
        });
</script>

Long way When do web-fonts load and can you pre-load them?

More on web font loader https://github.com/typekit/webfontloader .

fabric.js specific https://groups.google.com/forum/#!topic/fabricjs/sV_9xanu6Bg

like image 34
Ventoh Avatar answered Oct 28 '22 17:10

Ventoh


Using fabric.js and Google Web Fonts, the following code works for me:

Fiddle: http://jsfiddle.net/DanBrown180/vvL6f/

CSS

<Style>
@font-face {
font-family: 'Jolly Lodger';
font-style: normal;
font-weight: 400;
src: local('Jolly Lodger'), local('JollyLodger'),
url(http://themes.googleusercontent.com/static/fonts/jollylodger/v1/RX8HnkBgaEKQSHQyP9itiaRDOzjiPcYnFooOUGCOsRk.woff) format('woff');
}
<style>

Javascript

<script type = "text/javascript">
canvas = new fabric.Canvas('c'); 
var text = new fabric.Text("Web Font Example", {
                    left: 200,
                    top: 30,
                    fontFamily: 'Jolly Lodger',
                    fill: '#000',
                    fontSize: 60
                });

canvas.add(text);
</script>

HTML

<canvas id="c" height="200px" width="400px"></canvas>

Looks like it's because the Google Web Fonts css code uses:

src: local('Jolly Lodger'), local('JollyLodger')

in the CSS

like image 22
Dan Brown Avatar answered Oct 28 '22 17:10

Dan Brown


I had the same problem. Font renders correctly after some event is fired.. So after creating an object we can set it active:

var textSample = new fabric.Text(text, {
    fontFamily: "allstar",
});
canvas.add(textSample);
canvas.setActiveObject(textSample); // Selects the object
canvas.renderAll();
like image 42
TomMc Avatar answered Oct 28 '22 18:10

TomMc