3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SmartHRの村だよAdvent Calendar 2021

Day 19

Ruby/Railsで画像に文字を入れ込む

Last updated at Posted at 2021-12-18

こんにちは。エンジニアのronです。

SmartHRは、Rubykaigi 2021 Takeoutでスケジュールアプリを提供しました。
https://tech.smarthr.jp/entry/2021/11/02/204403

実はその中で、スケジュールページで設定した一言コメントがOGPに反映されるようにしていました。
これは、Twitterで自分の視聴予定をシェアしてワイワイ盛り上がってほしいという気持ちから実装したものです。

スクリーンショット 2021-12-18 13.56.45.png

今回は、どうやって画像の生成を行っているのかを解説していきたいと思います。

画像の生成方法

Rubyで画像を生成する方法はいくつかあります。

  • imagemagick
  • Thinreports
  • wkhtmltoimage
    などが候補になりますが、今回は改行などレイアウトの簡単さから、wkhtmltoimageを使うことにしました。

実際に生成する部分のコード

https://github.com/kufu/mie/blob/main/app/controllers/plans/ogps_controller.rb
こちらが、OGPの生成を行っているコントローラーのソースコードです。

class Plans::OgpsController < ApplicationController
  before_action :set_plan

  def show
    send_data IMGKit.new(get_html(@plan.description), quality: 20, width: 800).to_img(:png), type: 'image/png', disposition: 'inline'
  end

  private
  def set_plan
    @plan = Plan.find(params[:plan_id])
  end

  def get_html(body)
    <<~HTML
    <!DOCTYPE html>
<html lang="ja">
  <head>
	<meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
	<style>
    *,*::before,*::after{box-sizing:border-box}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin:0}ul[role="list"],ol[role="list"]{list-style:none}html:focus-within{scroll-behavior:smooth}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5}a:not([class]){text-decoration-skip-ink:auto}img,picture{max-width:100%;display:block}input,button,textarea,select{font:inherit}@media(prefers-reduced-motion:reduce){html:focus-within{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}
	  @charset "UTF-8";
	  html {
      font-family: 'Noto Sans CJK JP', 'Noto Color Emoji', 'Noto Emoji', sans-serif;
		  -ms-text-size-adjust: 100%;
		  -webkit-text-size-adjust: 100%;
	  }
    * {
      box-sizing: border-box;
    }
    .ogp-frame {
		  width: 1200px;
      height: 630px;
      overflow: hidden;
      background: no-repeat center url(data:image/png;#{ogp_background_image});
      padding: 44px 34px 240px 64px;
      line-height: 1.5;
      font-size: 58px;
      color: white;
      word-break: break-all;
    }
    .ogp-body {
      width: 100%;
      height: 100%;
      overflow-y: hidden;
      display: -webkit-box;
      -webkit-line-clamp: 4;
      -webkit-box-orient: vertical;
      padding: 0 10px 0 0;
    }
    
    .ogp-body::-webkit-scrollbar {
        display:none;
    }
	  
	</style>
  </head>
  <body><div class="ogp-frame"><div class="ogp-body">#{ERB::Util.h(body)}</div></div></body></html>
    HTML
  end

  def ogp_background_image
    # data-url
  end
end

wkhtmltoimageをrubyで扱うことができるIMGKitというGemを使用しています。使い方は非常に簡単で、
IMGKit.newの引数にHTML文字列(と、オプション)を渡し、to_imageを呼ぶことで、画像を得ることができます。

HTML自体は、背景画像をbackground-imageにして、その上に文字を表示しているだけのシンプルなものです。
overflowやwebkit-line-clampを使用して、文字が背景からはみ出すのを防止したり、長すぎる文章の場合は4行までしか表示しないようにしたりしています。

おわりに

画像に文字列を埋め込んでレイアウトすることはかなり簡単にできるということが伝われば幸いです。
OGPに限らず、アイディア次第で様々なサービスで利用できると思います。
面白いコラ画像ジェネレーターを作ったらぜひご一報ください!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?