WordPressによるテキスト投稿サイトを運営しているのですが(Web制作者の(苦笑)とタイケツというサイトです)、SNSでシェアされた時にもうちょっとインパクトを出したいと思い、投稿内容を反映したOGP・TwitterCards用のイメージを自動で生成させるようにしました。
ADs
Web制作者の(苦笑)botでご覧いただけます。
キャッシュの関係で過去記事は反映されていませんが、新しいツイートには自動生成された画像が使われています。
「クリエイターは人脈が大事」と、毎日のようにSNSを更新、交流に励む某氏。いいから仕事しろよ。 https://t.co/ibjOGLE51F
— Web制作者の(苦笑)bot (@ixi_ioi) 2017年10月6日
源真ゴシック(源ノ角ゴシック)のおかげで非常に美しい仕上がりです!
結構長い文字を入れましたが、問題なく読めますね。これでフォロワーやアクセスが増えれば…。
1.GDによってあらかじめ用意した背景画像に記事のタイトルを合成します。
2.生成した画像を保存し、記事のアイキャッチとして設定します。
3.metaタグを出力します。
という流れでやってみます。
全部functions.phpに書きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
//テーマのアイキャッチ機能を有効にする add_theme_support( 'post-thumbnails', array( 'post' ) ); //アイキャッチを生成する関数 function generateThumbnail($post_id,$post){ //アイキャッチが未設定で投稿タイプがpostの記事に処理をする場合。 //post以外の投稿タイプの場合は書き換えてください。 if(!has_post_thumbnail($post_id) && $post->post_type == 'post'){ //ベース(背景)の画像。この書き方だとテーマディレクトリの直下に置いてある $filename = dirname ( __FILE__ ) . '/base.jpg'; //フォントの指定。 //源真ゴシックPBold (http://jikasei.me/font/genshin/)を使わせていただきました。 $font = dirname ( __FILE__ ) . '/GenShinGothic-P-Bold.ttf'; $fontsize = 32; //フォントサイズ $margin = 30; //行間 //アイキャッチのファイル名は「投稿ID.jpg」にします。 $thumbname = $post_id . '.jpg'; //たとえば記事タイトルを合成する場合の例です。 //運営サイトによってはcontentだったりカスタムフィールドだったりしますので、適宜カスタムが必要です。 //記事タイトルを取得し、20文字ごとに分割(mb_wordwrapは別途定義してます) $txt = mb_wordwrap($post->post_title,20); //背景用画像のサイズを取得する $filesize = getimagesize($filename); $filew = $filesize[0]; $fileh = $filesize[1]; //ここからが本番です。 $img = imagecreatefromjpeg($filename); //JPEGを読み込み $color = imagecolorallocate($img,255,255,255); //文字色。 //テキストが合計何行になるかによって開始位置を設定(上下中央に持ってくるため) $count = count($txt); //文字数を計算 $height = ($fontsize + $margin) * $count; //テキスト部分の高さを計算 //テキスト開始位置。-10はbaseline分ですが、結果を見ながら目分量で調整する必要がありそう。 $y = (($fileh - $height) / 2) - 10; //文字一行ずつ出力していく foreach($txt as $val){ //文字エリアの座標を取得する関数です $pos = imagettfbbox($fontsize,0,$font,$val); //左右中央に持ってくるため、(画像幅-文字幅)/2を開始位置とします。 $x = ($filew - ($pos[4] - $pos[6])) / 2; //imagettftextで実際に文字を生成する imagettftext($img,$fontsize,0,$x,$y,$color,$font,$val); //縦方向の位置を文字サイズ+行間分ずらす(これでline-height:2ぐらいになるはず) $y = $y - ($pos[7] - $pos[1]) + $margin + $fontsize; } //ここからWordPressへの画像投稿処理 $wp_upload_dir = wp_upload_dir(); //アップロードディレクトリを取得 $thumbpath = $wp_upload_dir['path'] . '/' . $thumbname; //ファイルのフルパス //ここでファイルが実際に生成される。wp-content/uploads/ディレクトリを見てみてください。 imagejpeg($img,$thumbpath,100); //以下、WPの画像投稿処理 //https://www.imamura.biz/blog/16736 を参考にさせていただきました。 $wp_filetype = wp_check_filetype($thumbpath, null ); $attachment = array( 'guid' => $wp_upload_dir['url'] . '/' . basename( $thumbname ), 'post_mime_type' => $wp_filetype['type'], 'post_title' => preg_replace('/\.[^.]+$/', '', basename($thumbname)), 'post_content' => '', 'post_status' => 'inherit' ); require_once(ABSPATH . 'wp-admin/includes/image.php'); $attach_id = wp_insert_attachment( $attachment, $thumbpath, $post_id ); $attach_data = wp_generate_attachment_metadata( $attach_id, $thumbname ); wp_update_attachment_metadata( $attach_id, $attach_data ); //set_post_thumbnailがないとアイキャッチとして設定されません。 set_post_thumbnail($post_id, $attach_id); //GDのメモリ解放 imagedestroy($img); } } //上記の処理を新規投稿時に実行します。 add_action('wp_insert_post','generateThumbnail',100,2); |
記事タイトルが長くなることも考慮し、指定文字数で分割する関数を定義しています。
今回は配列で返してくれればよいので、implodeの部分は省いています。
1 2 3 4 5 6 7 8 9 |
function mb_wordwrap($str, $width=35) { $c = mb_strlen($str); $arr = []; for ($i=0; $i<=$c; $i+=$width) { $arr[] = mb_substr($str, $i, $width); } return $arr; } |
wp_head()へのアクションフックでmetaタグを出力します。
※og:titleなど足りないタグは別途補完してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function twitter_card(){ global $post; echo '<meta name="twitter:card" content="summary_large_image">'."\n"; //個別記事ページ+アイキャッチがある場合のみ if(is_single() && has_post_thumbnail($post->post_id)){ $ogp = wp_get_attachment_image_src(get_post_thumbnail_id(),'full'); } else { //個別記事ページ以外+アイキャッチがない場合はデフォルト画像を出します。 $ogp = get_bloginfo('template_url').'/common/img/ogp.jpg'; } echo '<meta name="twitter:image:src" content="' . $ogp .'">'."\n"; echo '<meta name="og:image" content="' . $ogp . '">'."\n"; } add_action('wp_head','twitter_card',100); |
上記は新規の投稿についてはアイキャッチ生成処理が動きますが、過去の記事には動きません。
過去記事にアイキャッチ生成処理を行いたい場合は、functions.phpに
1 2 3 4 5 6 7 8 9 10 11 12 |
function do_thumbnail(){ if($_GET['gen'] == '1'){ $posts = get_posts(array( numberposts => -1 )); foreach($posts as $post){ global $post; generateThumbnail($post->ID,$post); } } } add_action('wp_head','do_thumbnail'); |
と書き、
http://example.jp/?gen=1
のアドレスを叩くと記事全てに対してアイキャッチ生成処理が実行されます。
記事数が多いとタイムアウトになりますので、get_postsで全記事取得している部分を50件ずつにするとかsleep()をはさむなど、小分けして処理が走るようにしないといけないかもしれません。
素晴らしいフォントをありがとうございます。
源真ゴシック (げんしんゴシック)
wp_insert_attachmentの処理が参考になりました。
WordPressの「wp_insert_attachment」を使って、特定の投稿に対して添付ファイルをメディアライブラリにアップロードする
GDでの文字揃えの処理で参考になりました。
GDライブラリで文字を右寄せ出力する
多分Imagick使う方が楽です。
参考にしました(が、私のサーバーでは駄目っぽかった…)
PHPでImageMagickを使うImagickのコマンドサンプル
ADs
コメントはまだありません。