Kalsarikannint

サイト内検索

記事タイトルが埋め込まれたOGP画像を作る

あけましておめでとうございます。Kalsarikannintのフロントエンド担当・daiです。

QiitaとかZennとかイマドキのサイトをSNSなどでシェアしたとき、表示されるOGP画像に記事のタイトルが埋め込まれてるのをよく見かけると思います。

Kalsarikannintもイマドキの技術ブログも目指したい(願望) ので、この年末年始休みを使って、以下の各ページを参考に、WordPressで構築されているこのブログでもそれを実装してみたので、その方法などを紹介していきます!

参考:

つくったもの

最終的には、 functions.php に以下のコードを追記することで、記事を保存したタイミングで /wp-content/uploads/ogp/ogp_{記事ID}.jpg として記事タイトルが埋め込まれた画像を生成することができるようになりました。

// functions.php への記載内容
/**
 * Create OPG Image
 * 
 * タイトルを利用したOGP画像を生成する
 */
function create_ogp_image($post_id, $post) {
    $file_name = 'ogp_'.$post_id.'.jpg';
    $title = $post->post_title;
    $base_image = get_template_directory().'/images/ogp_template.jpg';
    $image = imagecreatefromjpeg($base_image);
    $color = imagecolorallocate($image, 0, 0, 0);
    $fontfile = get_template_directory().'/fonts/ZenKakuGothicNew-Black.ttf';

    $size = 36;
    $breakpoint = 20;

    if (mb_strwidth($title, 'UTF-8') > 120) {
        // 全体が60文字(= 20文字 * 3行)以上ならフォントサイズ変更 + 改行位置も変更
        $size = 20;
        $breakpoint = 35;
    }

    if (mb_strwidth($title, 'UTF-8') > $breakpoint * 2) {
        $max_count = mb_strwidth($title, 'UTF-8') / $breakpoint * 2;

        // 禁則処理に該当する文字
        $specialChars = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'ー', 'ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ッ', 'ャ', 'ュ', 'ョ', 'ヮ', '、', '。', '(', ')', '「', '」', '【', '】', 'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ', 'っ', 'ゃ', 'ゅ', 'ょ', 'ゎ'];

        $last_pos = 0;
        for ($count = 0; $count < $max_count; $count++) {
            for ($pos = $breakpoint + $last_pos; $pos > $last_pos; $pos--) {
                $char = mb_substr($title, $pos + 1, 1, 'UTF-8');

                if (!in_array($char, $specialChars)) {
                    // 禁則処理に触れない = 改行OK
                    $title = mb_substr($title, 0, $pos + 1)."\\n".mb_substr($title, $pos + 1);
                    $last_pos = $pos - 1;
                    break;

                } else if ($pos === $last_pos) {
                    // 禁則処理だらけなら強制改行しちゃお!
                    $title = mb_substr($title, $last_pos, $last_pos + $breakpoint)."\\n".mb_substr($title, $last_pos + 1);
                    $last_pos = $pos;
                    break;
                }
            }
        }
    }

    $angle = 0;
    $x = 100;
    $y = 300 + $size;

    // 文字列挿入
    imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $title);

    // OGP画像の保存場所がなければ作る
    if (!file_exists('wp-content/uploads/ogp')) {
        mkdir('wp-content/uploads/ogp', 0777);
    }
    
    // ファイル名を指定して画像出力
    imagejpeg($image, 'wp-content/uploads/ogp/'.$file_name);
}
add_action('save_post', 'create_ogp_image', 10, 2);

加えて、 functions.php へ以下のようなコードも追記し、記事ページでは上記で生成されたOGP画像を og:image として指定するように設定しています。

// functions.php への記載内容
add_action('wp_head', function() {
    $og_image = get_template_directory_uri().'/images/ogp_image.jpg';

    if (is_single()) {
        // 個別記事ページ
        $og_image = get_site_url().'/wp-content/uploads/ogp/ogp_'.get_the_ID().'.jpg';
    }

    echo '<meta property="og:image" content="'.$og_image.'" />';
});

上記の記述を追記するほかに、以下のファイルを用意する必要があります。

  • フォントファイル(テーマファイルディレクトリ配下の fonts ディレクトリを作成し保存)
  • テンプレートになる ogp_templete.jpg ファイル(テーマファイルディレクトリ配下の images ディレクトリへ保存)
  • 記事ページ以外のOGP画像となる ogp_image.jpg ファイル(同上)

OGP画像の生成方法

イマドキの環境を使っていれば、サーバーサイドでNode.jsを動かして、canvasを使って画像と文字の合成を行ったりするようですが、このサイトはCMSにWordPressを使っていることもあり、ごくごく一般的なレンタルサーバーで運用しているので、PHPのGDというライブラリを使って実装していきます。

GDライブラリがめちゃくちゃ優秀で、画像と文字の合成くらいなら、少ない記述であっという間に実装できてしまいました。

function createimage($title, $file_name) {
    $base_image = './images/ogp_templete.jpg';
    $image = imagecreatefromjpeg($base_image);
    $color = imagecolorallocate($image, 0, 0, 0);
    $fontfile = './fonts/ZenKakuGothicNew-Black.ttf';

    $fontsize = 36;
    $angle = 0;
    $x = 100;
    $y = 300 + $fontsize;
    
    // 合体っ!
    imagettftext($image, $fontsize, $angle, $x, $y,$color, $fontfile, $title);
    
    // 保存
    imagejpeg($image, './images/'.$file_name);
}

createimage("Hello World", "hw.jpg")

用意するのは、上記の関数が書かれたPHPファイルと、ベースとなる画像、それからフォントファイルです。フォントファイルはGoogleFontsから「Download」をクリックすると取得できます。

また、このままだと長いタイトルが来たときに画像の右端を突き抜けてしまうので、文字数に応じた改行処理を入れる必要があります。さらに、日本語には禁則処理といって改行してはいけない / しないほうがいい箇所があるので、それも力技で実装していきます。

禁則処理については、次のページを参考にしました:PHPで禁則処理を強引にやる | 無趣味の戯言

WordPressへの組み込み

とりあえずPHPだけでどうにかできることは分かったので、次はWordPressへの組み込みを考えていきます。

WordPressには、JavaScriptでいうところの「イベント」のような機能として「アクションフック」があり、記事を保存したタイミングで save_post フックが発火するようになっています。

ということで、 functions.phpsave_post フックをトリガーにしたOGP画像生成の関数を追記していきます。

function create_ogp_image($post_id, $post) {
    // 画像を生成する処理を記載
}

// save_post フックで create_ogp_image 関数をコールする
add_action('save_post', 'create_ogp_image', 10, 2);

add_action() 関数は、以下の引数を取ります。第三・第四引数は省略可能ですが、今回は第四引数で 2 を与えて投稿の内容も取得したかったので、第三・第四引数も指定しています。

  • 第一引数:トリガーとなるフック名
  • 第二引数:実行する関数名
  • 第三引数:プライオリティ(実行の優先順位)(初期値:10)
  • 第四引数:実行する関数が受け取る引数の数(利用するフックに応じて選択できる値が変わる)(初期値:1)

create_ogp_image() の中身は長くなるので、記事冒頭のコードからご覧ください…。

これで、記事を保存したタイミングで、 /wp-content/uploads/ogp/ogp_記事ID.jpg の画像ファイルが生成されるようになりました。

この記事でいうと、以下の画像が該当します。

headへのmetaタグの出力

画像が生成できるようになったので、次に、 <head> 内にOGP画像をお知らせするタグを埋め込んでいきます。

こちらも同じく functions.php に記述していきます。

add_action('wp_head', function() {
    $og_image = get_template_directory_uri().'/images/ogp_image.jpg';

    if (is_single()) {
        // 個別記事ページ
        $og_image = get_site_url().'/wp-content/uploads/ogp/ogp_'.get_the_ID().'.jpg';
    }

    echo '<meta property="og:image" content="'.$og_image.'" />';
});

wp_head フックが呼ばれたときに、上記処理を実行しています。今回はコールバック関数を直接記述するパターンでやってみました。関数名考えたくないときにはこのパターンもおすすめです。(どっちかで統一しろ

実際には、 og:titleog:url などもページの種類ごとに吐き出させているのですが、上記のコードでは og:image に焦点を当てて、それ以外は消しています。OGPの詳細は以下のページを参照してください。

https://ogp.me/#metadata


以上が、WordPressで記事のタイトル入りOGP画像を自動生成する一連の流れになります。

サーバーサイドでNode.jsを動かすことなく、PHPのGDライブラリだけでもここまで柔軟に合成処理が行えるのはなかなか魅力的だと思います。実際に実装してみると意外とシンプルなので、テーマやプラグインのカスタマイズに慣れている方であれば、すぐに組み込むことができるかと思います。ぜひ、自分好みに拡張・応用しながら、技術ブログやWordPressサイトでイマドキなOGP画像を作ってみてください!

Author dai

沖縄に住みながら、フルリモート情シスおじさんしてます。
フロントエンド開発とkintoneアプリのカスタマイズやプラグイン開発が得意分野です。
好きなビールは一番搾り。

WordPressのテーマ自作は怖くない 【第一回:最小構成でテーマを作ろう】

こんにちは。Kalsarikannintのフロントエンド担当・daiです。 WordPress、使ってますか?未だに無料CMSの中では右に出る者はいないレベルで支持されていますが、かくいうこのサイトも、WordPressで作られています。 そして、デザインの要となるテーマについては、ボイラープレートすら使わずに、イチから自作しています。 PHPが苦手なこともあり、ほんの数ヶ月前まではなるべくWordPressを避けてきた僕ですが、やってみると意外と怖くなかったよ、ってことをシリーズ(全4回の予定)でお伝えできればと思います。 いままで静的なサイトは作ったことがあるけど、「複雑そう」とか「既存のテーマをイジるのが怖い」といった理由でWordPressを避けていたコーダーの方の背中を押すきっかけになれば幸いです。 まずは最小構成で作ってみよう このサイトのもともとのテーマが「シンプル」「15年前のインターネット」だったこともあり、最小構成で成り立っています。WordPress初心者の方も、まずは「トップページ」と「記事ページ」だけのシンプルなサイトで作
wordpress

VSCodeをインストールしたらやること

こんにちは。dai です。 プログラミングで大切なのは、快適な開発環境を整えることです。VSCodeは非常に優れたエディタですが、デフォルトの設定のままでは物足りない部分もあります。この記事では、VSCodeをインストールした後に行っておきたい設定をまとめました。 これらの設定を行うことで、より効率的で快適な開発環境を手に入れることができます。それでは、具体的な設定項目を見ていきましょう。 フォント【Bizin Gothic】 Bizin Gothicは、最近好きなBIZ UD ゴシックと、過去に愛用していたRictyというフォントでも採用されていたInconsolataを組み合わして微調整された、プログラミングなどに最適なフォントです。 Bizin Gothicのようなプログラミングフォントを入れるメリットとして、見間違いを防げる、みたいなこともありますが、何より大事だと思うのが、フォントがキレイだとやる気が出る(汚いとやる気が起きない)ということだと思っています。モチベーション大事。 そんなプログラミングフォントですが、探してみると日本語に対応
develop

リモートワーカーの作業環境!沖縄在住ITエンジニアの自宅デスク

こんにちは。dai です。 2020年以降パンデミックの影響による在宅勤務の普及により、私たちの働き方は大きく変わりました。ITエンジニアにとって、快適で生産性の高い作業環境は何よりも重要です。 今回は、沖縄から都内の企業にフルリモートで勤務する僕の、自宅デスク環境をご紹介します! マイク【ArctisX】 少なくとも毎日朝夕のミーティングがあるのですが、イヤホン付属のマイクだと音が悪すぎたのでブラックフライデーに乗じてマイクを導入しちゃいました。 キーボード【RAZER Huntsman mini】 キーボードは散財小説ドリキンさんがいつの日かの動画で紹介されていた、RAZERの60%キーボード・Huntsman Miniを使っています。もともとはWindows用に買ったのですが、フルリモートで働き始めてから、キータイプするときのテンション上げぇてなぁってなったのでメインマシンのMacでも使うようになりました。しばらく使っていなかったのでまだ慣れが必要ですが、特にこうやってブログみたいな長文を書くときには、テンション上がっていいですね。 M
desk