TwitterにURLをシェアした時に表示される画像であるOGPは今やWebサービスを作る時に当たり前のものになってきました。しかもWebサービスの場合はだいたい投稿内容に応じて動的に生成を行うため、プログラムによる自動生成が必要となります。
各サービスで色々な作り方をされています。例えばPuppeteerというChromeを用いたライブラリを使用したり、ImageMagickなどのライブラリや、JavaScriptのcanvasを使う方法などです。
Laravel、というか素のPHPにもGDという標準ライブラリがあり、そちらでも簡単に作成することが出来ますのでその方法です。ちなみにこういうOGPを作成します。
サーバーでGDが有効になっている必要があります。また、pngやjpeg等の必要なライブラリも有効になっている必要があり、且つ今回は文字を入れるのでfreetypeも有効になっている必要があります。phpinfoで各サポートが有効になっているかを確認してください。
今回はそれっぽく見せるために最初に背景画像を描画します。そのためまずぱくたそから適当な背景画像をお借りしました。また、フォントも必要ですので無心をお借りしています。
コードをそのまま載っけます。普通にPHPで画像を作っているだけです。例えば今回はPostControllerに追記します。
public function ogp(Post $post)
{
// OGPのサイズ
$w = 600;
$h = 315;
// 1行の文字数
$partLength = 10;
$fontSize = 30;
$fontPath = resource_path('font/mushin.otf');
// 画像を作成
$image = \imagecreatetruecolor($w, $h);
// 背景画像を描画
$bg = \imagecreatefromjpeg(resource_path('image/HIRO95_yuubaenokage_TP_V4.jpg'));
imagecopyresampled($image, $bg, 0, 0, 0, 0, $w, $h, 800, 533);
// 色を作成
$white = imagecolorallocate($image, 255, 255, 255);
$grey = imagecolorallocate($image, 128, 128, 128);
// 各行に分割
$parts = [];
$length = mb_strlen($post->title);
for ($start = 0; $start < $length; $start += $partLength) {
$parts[] = mb_substr($post->title, $start, $partLength);
}
// テキストの影を描画
$this->drawParts($image, $parts, $w, $h, $fontSize, $fontPath, $grey, 3);
// テキストを描画
$this->drawParts($image, $parts, $w, $h, $fontSize, $fontPath, $white);
ob_start();
imagepng($image);
$content = ob_get_clean();
// 画像としてレスポンスを返す
return response($content)
->header('Content-Type', 'image/png');
}
/**
* 各行の描画メソッド
*/
private function drawParts($image, $parts, $w, $h, $fontSize, $fontPath, $color, $offset = 0)
{
foreach ($parts as $i => $part) {
// サイズを計算
$box = \imagettfbbox($fontSize, 0, $fontPath, $part);
$boxWidth = $box[4] - $box[6];
$boxHeight = $box[1] - $box[7];
// 位置を計算
$x = ($w - $boxWidth) / 2;
$y = $h / 2 + $boxHeight / 2 - $boxHeight * count($parts) * 0.5 + $boxHeight * $i;
\imagettftext($image, $fontSize, 0, $x + $offset, $y + $offset, $color, $fontPath, $part);
}
}
routes/web.phpに画像を表示するためのルーティングを設定します。これで http://localhost:8000/posts/1/ogp.png
のようなURLでアクセスできるようになります。
Route::get('posts/{id}/ogp.png', '[email protected]');
あとは詳細ページに下記のようなメタタグを追加しておけば詳細ページのURLをツイートするだけで画像が表示されるようになります。
@section('additionalMeta')
<meta property="og:image" content="{{ config('app.url') }}/posts/{{ $post->id }}/ogp.png">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="{{ config('app.url') }}/posts/{{ $post->id }}/ogp.png">
@endsection
(↑この例だと実際には共通レイアウトに @yield('addtionalMeta')
を追記する必要があります)
TwitterのCard validatorにそのURLを入力すれば正しく表示されるかテストが出来ます。
全部プログラムで描画しているため改造する時のメンテナンス等は大変かもしれませんが、とりあえずぱぱっと作っておきたいときなどは非常に便利です。 Have a happy OGP life!
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント