node.js에서는 블로그 스타일의 아이 캐치 이미지를 동적으로 생성합니다.

19448 단어 캔버스Node.js
Hatena 블로그에서 이미지가 설정되지 않은 블로그 게시물을 공유하면 블로그 제목과 본문에서 이미지를 생성하여 아이 캐치로 설정하는 기능이 출시되었습니다. 되어 화제가 되었습니다.

요즘 블로그 기사에 한하지 않고 다양한 서비스에서 콘텐츠를 SNS 공유할 때 어떻게 눈에 띄게 할까라는 부분인 아이 캐치의 OGP 이미지 설정의 중요성은 말할 필요도 없다고 생각합니다.

자신도 운영하고 있는 서비스로 동적으로 OGP를 작성하는 이른바 「OGP예」를 잘 하고 있습니다만, 향후 점점 필요성이 높아질 것으로 생각해, OGP예용의 두드려대로 하는 처리 템플릿을 만들었습니다.

아티팩트 샘플





소스 코드


const fs = require("fs");
const { createCanvas } = require('canvas')
const base64 = require('urlsafe-base64');
// canvasの横幅
let canvasWidth = 1200;
// canvasの縦幅
let canvasHeight = 630;
let canvas;
let ctx;

// タイトル部分の文字スタイル
const titleFontStyle = {
    font: 'bold 73px "Noto Sans CJK JP"',
    lineHeight: 80,
    color: '#333333'
};
// 本文部分の文字スタイル
const bodyFontStyle = {
    font: '30px "Noto Sans CJK JP"',
    lineHeight: 38,
    color: '#666666'
};
// 画像内側余白
let padding = 80;

// 背景色
let backgroundColor = "#d3ffb1";

let generate = (title, body, fileName) => {
    // 空白のcanvasを作成
    canvas = createCanvas(canvasWidth, canvasHeight)
    // コンテキスト取得
    ctx = canvas.getContext('2d')
    // -----
    // タイトル描画
    // -----
    // 行長さ
    let lineWidth = canvasWidth - (padding * 2);
    // フォント設定
    ctx.font = titleFontStyle.font;
    // 行数の割り出し
    let titleLines = splitByMeasureWidth(title, lineWidth, ctx);
    let titleLineCnt = titleLines.length;
    // タイトル分の高さ
    let titleHeight = titleLines.length * titleFontStyle.lineHeight;

    // -----
    // 本文部分描画
    // -----
    let titleMargin = 40;
    // フォント設定
    ctx.font = bodyFontStyle.font;
    // 行数の割り出し
    let bodyLines = splitByMeasureWidth(body, lineWidth, ctx);
    let bodyLineCnt = bodyLines.length;

    // 本文分の高さ
    let bodyHeight = bodyLines.length * bodyFontStyle.lineHeight;

    // 行高さと余白が最小高さ(630)を上回る場合はカンバスをリサイズする
    let contentHeight = titleHeight + titleMargin + bodyHeight + (padding * 2);
    if (canvasHeight < contentHeight) {
        canvasHeight = contentHeight
        canvas = createCanvas(canvasWidth, contentHeight)
        ctx = canvas.getContext('2d')
    }

    // 取り敢えず背景色をつける
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight)

    // 文字描画のベースラインを設定
    ctx.textBaseline = 'top';
    // タイトルを描画
    ctx.fillStyle = titleFontStyle.color;
    ctx.font = titleFontStyle.font;
    for (let index = 0; index < titleLineCnt; index++) {
        const element = titleLines[index];
        ctx.fillText(element, padding, padding + (titleFontStyle.lineHeight * index))
    }
    // 本文を描画
    ctx.fillStyle = bodyFontStyle.color;
    ctx.font = bodyFontStyle.font;
    for (let index = 0; index < bodyLineCnt; index++) {
        const element = bodyLines[index];
        // タイトル分の高さと余白を加算する
        ctx.fillText(element, padding, padding + (titleHeight + titleMargin) + (bodyFontStyle.lineHeight * index))
    }

    let b64 = canvas.toDataURL().split(',');
    let img = base64.decode(b64[1]);
    // ファイル保存
    fs.writeFile(fileName, img, function (err) {
        console.log(err);
    });
}

function splitByMeasureWidth(str, maxWidth, context) {
    // サロゲートペアを考慮した文字分割
    let chars = Array.from(str);
    let line = '';
    let lines = [];
    for (let index = 0; index < chars.length; index++) {
        if (maxWidth <= context.measureText(line + chars[index]).width) {
            lines.push(line);
            line = chars[index];
        }
        else {
            line += chars[index];
        }
    }
    lines.push(line);
    return lines;
}

module.exports = {
    generate: generate
};


작동에 필요한 리소스



처리 라이브러리(node-canvas)



htps : // 기주 b. 코 m / 오토 마치 c / 그래서 칸 ゔ
이미지를 만들려면 node-canvas을 사용합니다.
설치 및 컴파일에 필요한 리소스를 설정하는 방법에 대해서는 해당 라이브러리의 Readme를 참조하여 환경에 맞게 준비하십시오.

글꼴



이번에는 Noto 글꼴을 사용하고 운영 환경에 설치되어 있다고 가정합니다.
동적으로 이미지를 만들 때 글꼴에 따라 사용 라이센스가 다를 수 있으므로주의가 필요합니다.

사용법


var ogpGenerator = require('./ogpGenerator');
ogpGenerator.generate(
    'こういう画像が動的に作成できます。',
    'そのころわたくしは、モリーオ市の博物局に勤めて居りました。十八等官でしたから役所のなかでも、ずうっと下の方でしたし俸給ほうきゅうもほんのわずかでしたが、受持ちが標本の採集や整理で生れ付き好きなことでしたから、わたくしは毎日ずいぶん愉快にはたらきました。',
    './YOUR_FILE_NAME.jpg'
);

배경에 이미지를 붙이거나, 개행 코드에 대응하거나 같은 것은 필요에 따라 적절히 부디.

좋은 웹페이지 즐겨찾기