Last updated: December 17, 2023最后更新:2023年12月17日
↓↓↓
Generating Open Graph Images in Eleventy在 Eleventy 中生成开放图图像
↑↑↑
I added the og:media
image tags yesterday, and the approach seems to work, so I’m going to share it in this post.我昨天添加了 og:media
图像标签,这种方法似乎有效,所以我将在这篇文章中分享它。
I am using the filter functions and generating the raster images directly inside of the filter with node-canvas
, as described in this article.我正在使用过滤器函数,并使用 node-canvas
直接在过滤器内生成光栅图像,如本文所述。
First I added the meta tags to my default layout. I called the filter previews
, and I will be using the title
variable as the argument.首先,我将元标记添加到我的默认布局中。我调用了筛选previews
,我将使用 title
变量作为参数。
<meta property="og:image" content="{{ title | previews }}" />
Then I wrote the filter.然后我写了过滤器。
const fs = require('fs');
const path = require('path');
const { createCanvas, registerFont } = require("canvas");
...
eleventyConfig.addFilter("previews", async function (title) {
// register custom fonts, if you want to use any
// this step has to be done before creating the canvas
registerFont('./custom-font.ttf', { family: 'Custom Font' });
// set layout variables
const width = 1200;
const height = 630;
// create the canvas
const canvas = createCanvas(width, height);
const context = canvas.getContext("2d");
// get the output path
const output = path.dirname(this.page.outputPath);
// set the filename to the slug of the page, or "preview" as a backup
const filename = this.page.fileSlug.trim() || 'preview';
// set the extension
const ext = "png";
// create the full output path
const filepath = path.join(output, `${filename}.${ext}`);
// maybe the file already exists - in that case, just return the relative path
if (fs.existsSync(filepath)) {
return `${filename}.${ext}`;
}
// canvas won't automatically divide the header into multiple lines,
// so we have to do it manually - in my case, there'll be at most
// six words in one line
const wordsPerLine = 6;
const header = title
.split(' ')
.reduce((result, word, index) => {
const line = Math.floor(index / wordsPerLine);
if (!result[line]) {
result[line] = []; // begin new line
}
result[line].push(word);
return result;
}, [])
.map(line => line.join(' '))
.join('\n');
// set the canvas background
context.fillStyle = "#222222";
context.fillRect(0, 0, width, height);
// set the header
const fontSize = 30;
const lineCount = header.match(/\n/g)?.length ?? 0;
context.fillStyle = "#ffffff";
context.font = `${fontSize}px 'Custom Font'`;
context.textAlign = "center";
context.fillText(header, width / 2, (height - lineCount * fontSize) / 2);
// create the image
const buffer = canvas.toBuffer("image/png");
// create the output directory if it doesn't already exist
if (!fs.existsSync(output)) {
fs.mkdirSync(output, { recursive: true });
}
// write the file
fs.writeFileSync(filepath, buffer);
// return the relative file path
return `${filename}.${ext}`;
});
This is the bare-bones set-up, without any decorations, or the name of the author, or anything like that, but this article and the node-canvas documentation describe how to add more things.这是最基本的设置,没有任何装饰,也没有作者的名字,或者类似的东西,但这篇文章和节点画布文档描述了如何添加更多的东西。