node-canvas自定义Quote字体未生效问题求助
自定义Quote字体未在node-canvas中生效的排查与修复
问题概述
使用node-canvas生成图片时,注册的自定义Quote字体未应用到文本中,代码文件index.js与Quote.ttf位于同一根目录,核心代码如下:
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();
排查出的关键问题
- 字体注册时机错误:
registerFont必须在createCanvas之前调用,canvas实例创建后注册字体无法被已创建的上下文识别。 - 配置参数拼写错误:
registerFont的配置项中,样式参数应为小写的style,而非大写的Style,参数名不匹配会导致字体样式注册失败。 - font属性格式错误:设置
context.font时的字符串存在多余单引号和嵌套错误,正确的字体格式应为fontSize + 'px Quote'或fontSize + 'px "Quote"',错误格式会导致canvas无法正确识别字体家族。
修复后的完整代码
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 }; // 提前注册字体,放在createCanvas之前 registerFont('./Quote.ttf', { family: 'Quote', style: 'Regular' }); 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); 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; // 修正font属性的格式 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();
修复说明
- 将
registerFont移至createCanvas之前,确保字体在canvas实例创建时已完成注册。 - 修正
registerFont配置中的Style为style,匹配官方API的参数名。 - 简化
context.font的字符串格式,使用模板字符串生成正确的字体声明,避免多余引号导致的识别问题。
内容的提问来源于stack exchange,提问作者Satyam Kumar
相关产品推荐
相关产品推荐

