I have a demo here: https://codepen.io/Jsbbvk/pen/KKXNPYO
var canvas = new fabric.Canvas("canvas");
const text = new fabric.IText("sample text")
text.set({
fontFamily: "Impact",
left: (this.canvas.width - text.width) / 2,
top: (this.canvas.height - text.height) / 2,
})
canvas.add(text)
canvas.requestRenderAll()
If you visit this codepen on a mobile device, you'll see that the Impact font doesn't load. However, visiting this codepen on a desktop will work. Is there a fix to this?
Actually, the term "web safe fonts" is just plain wrong! (see also: "Impact" font not working on mobile Chrome
loadFonts(fontsToLoad)
(based on FontFace.load()
method)JS:
async function initFabric() {
var canvas = new fabric.Canvas("canvas");
const text = new fabric.IText("sample text");
let canvasContainer = document.querySelector(".canvas-container");
//load fonts if necessary
let fontsToLoad = checkFontAvailability(fonts);
await loadFonts(fontsToLoad);
text.set({
fontFamily: "Impact",
left: (this.canvas.width - text.width) / 2,
top: (this.canvas.height - text.height) / 2
});
canvas.add(text);
canvas.requestRenderAll();
}
/**
* fonts to check
*/
let fonts = [{
'font-family': 'Arial',
'font-style': 'normal',
'font-weight': 400,
'src': 'https://fonts.gstatic.com/s/anton/v23/1Ptgg87LROyAm3Kz-C8.woff2'
},
{
'font-family': 'Times New Roman',
'font-style': 'normal',
'font-weight': 400,
'src': 'https://fonts.gstatic.com/s/anton/v23/1Ptgg87LROyAm3Kz-C8.woff2'
},
{
// Inter as replacement
'font-family': 'Helvetica',
'font-style': 'normal',
'font-weight': 400,
'src': 'https://fonts.gstatic.com/s/inter/v12/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7.woff2'
},
{
// Anton as replacement
'font-family': 'Impact',
'font-style': 'normal',
'font-weight': 400,
'src': 'https://fonts.gstatic.com/s/anton/v23/1Ptgg87LROyAm3Kz-C8.woff2'
},
]
/**
* init fabric after font check
*/
initFabric();
async function initFabric() {
var canvas = new fabric.Canvas("canvas");
const text = new fabric.IText("sample text");
let canvasContainer = document.querySelector('.canvas-container');
//load fonts if necessary
let fontsToLoad = checkFontAvailability(fonts);
await loadFonts(fontsToLoad);
text.set({
fontFamily: "Impact",
left: (this.canvas.width - text.width) / 2,
top: (this.canvas.height - text.height) / 2,
})
canvas.add(text)
canvas.requestRenderAll()
//add buttons
fonts.forEach(function(font) {
let fontFamily = font['font-family']
let btn = document.createElement('button')
btn.setAttribute('type', 'button')
btn.classList.add('btn-font');
btn.textContent = fontFamily
canvasContainer.parentNode.insertBefore(btn, canvasContainer);
btn.addEventListener("click", () => {
text.fontFamily = fontFamily
canvas.renderAll()
})
})
}
function checkFontAvailability(fonts) {
let info = [];
let fontsToLoad = [];
if (fonts.length) {
fonts.forEach(function(font) {
let fontFamily = font['font-family'];
let fontApplied = document.fonts.check(`12px ${fontFamily}`);
if (!fontApplied) {
fontsToLoad.push(font)
}
})
}
return fontsToLoad;
}
async function loadFonts(fontsToLoad) {
if (fontsToLoad.length) {
for (let i = 0; i < fontsToLoad.length; i++) {
let fontProps = fontsToLoad[i];
let fontFamily = fontProps['font-family'];
let fontWeight = fontProps['font-weight'];
let fontStyle = fontProps['font-style'];
let fontUrl = Array.isArray(fontProps['src']) ? fontProps['src'][0][0] : fontProps[
'src'];
if (fontUrl.indexOf('url(') === -1) {
fontUrl = 'url(' + fontUrl + ')';
}
let fontFormat = fontProps['src'][0][1] ? fontProps['src'][1] : '';
const font = new FontFace(fontFamily, fontUrl);
font.weight = fontWeight;
font.style = fontStyle;
await font.load();
document.fonts.add(font);
console.log(fontFamily, 'loaded')
// apply font styles to invisible elements
let fontDOMEl = document.createElement('div');
fontDOMEl.textContent = '';
document.body.appendChild(fontDOMEl);
fontDOMEl.setAttribute(
"style",
`position:fixed; height:0; width:0; overflow:hidden; font-family:${fontFamily}; font-weight:${fontWeight}; font-style:${fontStyle}`
);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.3.0/fabric.min.js"></script>
<canvas width="300" height="300" id="canvas"></canvas>
loadFonts()
will append invisible elements to your DOM with the desired font-families applied.
This will ensure the loaded fonts are also available for canvas
elements.