我想在画布上居中文本。水平看起来不错,但垂直仍然是一个问题:我不知道如何以编程方式做到这一点。
我以前可以用 1 行来做到这一点,但现在我想让它适用于多行文本。
现在的图像如下所示:
文本应该定位得更高一点,还是我弄错了?
这是代码:
const fs = require('fs')
const { createCanvas } = require('canvas')
const width = 2000;
const height = 2000;
const canvas = createCanvas(width, height)
const context = canvas.getContext('2d')
context.fillStyle = '#edf4ff'
context.fillRect(0, 0, width, height)
context.textAlign = 'center'
context.textBaseline = 'middle';
context.fillStyle = '#002763'
const fontSizeUsed = drawMultilineText(
context,
"This is yet another test",
{
rect: {
x: 1000,
y: 0,
width: 2000,
height: 2000
},
font: 'Arial',
verbose: true,
lineHeight: 1,
minFontSize: 100,
maxFontSize: 200
}
)
const buffer = canvas.toBuffer('image/png')
fs.writeFileSync('./image.png', buffer)
应该对齐文本的关键函数drawMultiLineText是这个:
function drawMultilineText(ctx, text, opts) {
// Default options
if(!opts)
opts = {}
if (!opts.font)
opts.font = 'sans-serif'
if (typeof opts.stroke == 'undefined')
opts.stroke = false
if (typeof opts.verbose == 'undefined')
opts.verbose = false
if (!opts.rect)
opts.rect = {
x: 0,
y: 0,
width: ctx.canvas.width,
height: ctx.canvas.height
}
if (!opts.lineHeight)
opts.lineHeight = 1.1
if (!opts.minFontSize)
opts.minFontSize = 30
if (!opts.maxFontSize)
opts.maxFontSize = 100
// Default log function is console.log - Note: if verbose il false, nothing will be logged anyway
if (!opts.logFunction)
opts.logFunction = function(message) { console.log(message) }
const words = require('words-array')(text)
if (opts.verbose) opts.logFunction('Text contains ' + words.length + ' words')
var lines = []
let y; //New Line
// Finds max font size which can be used to print whole text in opts.rec
for (var fontSize = opts.minFontSize; fontSize <= opts.maxFontSize; fontSize++) {
// Line height
var lineHeight = fontSize * opts.lineHeight
// Set font for testing with measureText()
ctx.font = ' ' + fontSize + 'px ' + opts.font
// Start
var x = opts.rect.x;
y = fontSize; //modified line
lines = []
var line = ''
// Cycles on words
for (var word of words) {
// Add next word to line
var linePlus = line + word + ' '
// If added word exceeds rect width...
if (ctx.measureText(linePlus).width > (opts.rect.width)) {
// ..."prints" (save) the line without last word
lines.push({ text: line, x: x, y: y })
// New line with ctx last word
line = word + ' '
y += lineHeight
} else {
// ...continues appending words
line = linePlus
}
}
// "Print" (save) last line
lines.push({ text: line, x: x, y: y })
// If bottom of rect is reached then breaks "fontSize" cycle
if (y > opts.rect.height)
break
}
if (opts.verbose) opts.logFunction("Font used: " + ctx.font);
const offset = opts.rect.y + (opts.rect.height - y) / 2; //New line, calculates offset
for (var line of lines)
// Fill or stroke
if (opts.stroke)
ctx.strokeText(line.text.trim(), line.x, line.y + offset) //modified line
else
ctx.fillText(line.text.trim(), line.x, line.y + offset) //modified line
// Returns font size
return fontSize
}
我不在浏览器中,我正在使用 node.js。