javascriptnode.jscanvashtml5-canvasnode-canvas

node-canvas font not applied to the text


const { createCanvas, loadImage, registerFont } = require('canvas');
const fs = require('fs');

const myfact = "when a person dies, they have 7 minutes of brain activity left."
const settings = {
  txtarea: {
    x: 540,
    y: 0,
    width: 864,
    height: 1080
  },
  font: 'Quote',
  lineHeight: 1,
  minFontSize: 50,
  maxFontSize: 70
};

async function generateImage() {
  const canvas = createCanvas(1080, 1080);
  const context = canvas.getContext('2d');

  const bgimage = await loadImage("./background.jpg");
  context.drawImage(bgimage, 0, 0, 1080, 1080);

  registerFont('./Quote.ttf', { family: 'Quote', Style: 'Regular' });
  
  context.textAlign = 'center';
  context.textBaseline = 'middle';
  context.fillStyle = '#fff';

  drawMultiLineFact(context, myfact, settings);

  const buffer = canvas.toBuffer('image/png');
  fs.writeFileSync('./image.png', buffer);
};

function drawMultiLineFact(context, myfact, settings) {
  const words = require('words-array')(myfact);
  var lines = [];
  let y;
  let lastFittingLines;
  let lastFittingFont;
  let lastFittingY;
  let lastFittingLineHeight;
  
  for (var fontSize = settings.minFontSize; fontSize <= settings.maxFontSize; fontSize++) {
    var lineHeight = fontSize * settings.lineHeight;
    context.font = `'` + fontSize + `px "Quote"'`
    var x = settings.txtarea.x;
    y = lineHeight;
    lines = []
    var line = ''

    for (var word of words) {
      var linePlus = line + word + ' '
      if (context.measureText(linePlus).width > (settings.txtarea.width)) {
        lines.push({ text: line, x: x, y: y });
        line = word + ' '
        y += lineHeight
      } else {
        line = linePlus
      };
    };
    lines.push({ text: line, x: x, y: y });
    if (y > settings.txtarea.height) break;
    lastFittingLines = lines;
    lastFittingFont = context.font;
    lastFittingY = y;
    lastFittingLineHeight = lineHeight;
  };
  lines = lastFittingLines;
  context.font = lastFittingFont;
  const offset = settings.txtarea.y - lastFittingLineHeight / 2 + (settings.txtarea.height - lastFittingY) / 2;
  for (var line of lines) {
    context.fillText(line.text.trim(), line.x, line.y + offset);
  };
};

generateImage();

I am using the above code to write text but the font i am using is not applied to the text.

I think there is problem in registering font.

file

index.js quote.js

both in same root folder.

and idk why they say your code is mostly the code . i written so so so may thing lol egnore this paragraph.

and idk why they say your code is mostly the code . i written so so so may thing lol egnore this paragraph.

and idk why they say your code is mostly the code . i written so so so may thing lol egnore this paragraph.


Solution

  • From the project's Readme:

    registerFont()

    registerFont(path: string, { family: string, weight?: string, style?: string }) => void
    

    To use a font file that is not installed as a system font, use registerFont() to register the font with Canvas. This must be done before the Canvas is created.

    (emphasize not mine)

    You must call it before you create your canvas.

    Then, your font declaration is broken. There are ' single quotes that shouldn't be there. Change it simply

    context.font = fontSize + `px Quote`