canvas-with-twemoji
Version:
Load emojis on canvas
88 lines (72 loc) • 2.32 kB
JavaScript
const splitEntitiesFromText = require('./utils/splitEntitiesFromText');
const loadTwemojiImageByUrl = require('./utils/loadTwemojiImageByUrl');
const getFontSizeByCssFont = require('./utils/getFontSizeByCssFont');
const measureText = require('./measureText');
const { Canvas } = require('canvas');
module.exports = async function drawTextWithEmoji (
context,
fillType,
text,
x,
y,
{
maxWidth = Infinity,
emojiSideMarginPercent = 0.1,
emojiTopMarginPercent = 0.1
} = {}
) {
const textEntities = splitEntitiesFromText(text);
const fontSize = getFontSizeByCssFont(context.font);
const baseLine = context.measureText('').alphabeticBaseline;
const textAlign = context.textAlign;
const transform = context.currentTransform;
const emojiSideMargin = fontSize * emojiSideMarginPercent;
const emojiTopMargin = fontSize * emojiTopMarginPercent;
const textWidth = measureText(context, text, { emojiSideMarginPercent }).width;
let textLeftMargin = 0;
if (!['', 'left', 'start'].includes(textAlign)) {
context.textAlign = 'left';
switch (textAlign) {
case 'center':
textLeftMargin = -textWidth / 2;
break;
case 'right':
case 'end':
textLeftMargin = -textWidth;
break;
}
}
let currentWidth = 0;
if (textWidth > maxWidth) {
let scale = maxWidth / textWidth;
context.setTransform(scale, 0, 0, 1, 0, 0);
x = x / scale;
}
for (let i = 0; i < textEntities.length; i++) {
const entity = textEntities[i];
if (typeof entity === 'string') {
if (fillType === 'fill') {
context.fillText(entity, textLeftMargin + x + currentWidth, y);
} else {
context.strokeText(entity, textLeftMargin + x + currentWidth, y);
}
currentWidth += context.measureText(entity).width;
} else {
const emoji = await loadTwemojiImageByUrl(entity.url);
emoji.width = fontSize;
emoji.height = fontSize;
context.drawImage(
emoji,
textLeftMargin + x + currentWidth + emojiSideMargin,
y + emojiTopMargin - fontSize - baseLine,
fontSize,
fontSize
);
currentWidth += fontSize + (emojiSideMargin * 2);
}
}
if (textAlign) {
context.textAlign = textAlign;
}
context.setTransform(transform);
}