Текст не будет правильно центрироваться по вертикали в canvas с помощью JavaScript

#javascript

#javascript

Вопрос:

Я новичок в JS, только что закончил курс.

У меня есть веб-приложение на PHP (с использованием библиотеки GD), которое работает хорошо, но я хочу воссоздать его с помощью JS (без jQuery). Приложение генерирует изображение размером 512 x 512 из текста на основе пользовательского ввода. Можно добавить только 1-3 буквы и / или цифры, поэтому у меня нет кучи текста, который нужно обернуть или что-то в этом роде.

После прочтения различных сообщений на форумах и руководств я все еще не могу сделать текст вертикально центрированным в canvas.

Это HTML-код canvas:

 <canvas class="border" width="512" height="512"></canvas>
  

На данный момент это окончательный JS-код, который почти работает:

 const form = document.querySelector('form');
const canvas = document.querySelector('canvas');
const inputText = document.querySelector('#inputText');
const selectFont = document.querySelector('#selectFont');
const inputFontSize = document.querySelector('#inputFontSize');
const inputBgColor = document.querySelector('#inputBgColor');
const inputTextColor = document.querySelector('#inputTextColor');
const context = canvas.getContext('2d');

fontFamilies = [
    new FontFace ('Roboto', 'url(/assets/fonts/roboto-v20-latin-700.woff2)'),
    new FontFace ('Merriweather', 'url(/assets/fonts/merriweather-v22-latin-900.woff2)'),
    new FontFace ('Dancing Script', 'url(/assets/fonts/dancing-script-v15-latin-700.woff2)')
];

form.addEventListener('submit', e => {
    e.preventDefault();    

    const getText = inputText.value.trim();
        
    // const textWidth = context.measureText(getText).width;    

    context.fillStyle = inputBgColor.value; 
    context.fillRect(0, 0, 512, 512);     
    context.fillStyle = inputTextColor.value;

    context.textBaseline = 'middle'; 
    context.textAlign = 'center';     

    fontFamilies.forEach(fontFamily => {

        fontFamily.load().then(font => {

            document.fonts.add(font);
    
            if (selectFont.value === 'roboto') {
                context.font = inputFontSize.value   'px'   ' '   'Roboto';
            } else if (selectFont.value === 'merriweather') {
                context.font = inputFontSize.value   'px'   ' '   'Merriweather';
            } else if (selectFont.value === 'dancingScript') {
                context.font = inputFontSize.value   'px'   ' '   'Dancing Script';
            }
            
            context.fillText(getText, canvas.width / 2, canvas.height / 2, 512);
            
        });
    });     
});
  

Это конечный результат:

введите описание изображения здесь

Как вы можете видеть, нижнее поле явно больше.

Я также:

  • Использовались разные семейства шрифтов, включая системные;
  • Использовались оба формата .ttf и .woff2;
  • Переключенные браузеры.

Комментарии:

1. Установка атрибута textBaseline контекста в значение «middle» устанавливает его в середину квадрата шрифта, а не в вертикальную середину текущего текста. Значение em square должно учитывать высоту всех букв в шрифте, включая буквы с нисходящими (f, q, p и т. Д.)

2. Спасибо! Я проверил «em square», и теперь это определенно имеет смысл. Если вы знаете какой-либо способ справиться с этим или альтернативный способ, пожалуйста, дайте мне знать.