WEB・アプリ開発

Middlemanでサムネイル画像を作る方法

Middlemanでこのようなサムネイル画像を作る方法をご紹介します。このようなサムネイル画像をMiddlemanでも作ることができます。

Middlemanで作ったサムネイル画像(メイン)

サイドバーによくある小さなサムネイルももちろん可能です。

Middlemanで作ったサムネイル画像(サイドバー)

サムネイルを生成するためのgem

Middlemanのサムネイル生成のgemで有名なのが次の2つです。

両方試したのですが、私は前者を採用しました。というのは、後者はサムネイルを生成する画像があるディレクトリを指定する必要があったためです。画像を特定のディレクトリにまとめている人はよいのですが、自分の場合は下のような記事ごとのディレクトリに画像を保存してありました。

source/articles/2016-11/02-tom-yum-goong-noodle/images/

なので、保存ディレクトリを気にしなくてよい、前者を採用しました。

middleman-simple-thumbnailerの使い方

導入方法

Gemfileに以下を追記しbundle installを実行します。


config.rbに以下を追記すれば使えるようになります。

うまくbundle installできなかったり、正常に動かない場合

お使いの端末にGraphicsMagickというモジュールをインストールする必要がある場合があります。

Macでhomebrewをお使いのかたは下のようにインストールできます。

使い方

View側でimage_tagというヘルパーメソッドを次のように使うことができます。


image_tagはもともとMiddlemanにあるヘルパーメソッドですが、middleman-simple-thumbnailerをインストールすると、resize_toというオプションが追加されます。これに生成したいサムネイルのサイズを指定してあげるだけです。

image_tagがやってくれることはざっくり次の2点です。

  •  imageで指定した画像のresize_toで指定したサイズのバージョンを作る
  • src属性に生成したサムネイルのパスを指定したimgタグを出力する

縦と横の両方それぞれ指定できるわけではない

上の例では'50x50'と指定していますが、縦と横のサイズが違う場合、どちらも50pxにしてくれるというわけではないようです。長い方を50にし、縦横の比率を変えずに短いほうの長さが決まるようです。

なので、縦横比を変えたい場合は、CSSのheigtやwidth属性で制御するのがよいでしょう。

記事の最初にでてくる画像をサムネイルにする方法

先ほどの例では、imageのところに、いちいちサムネイル化したい画像のパスを指定しなければなりません。通常のサイトやブログ運営では、記事の一番最初に出てくる画像を勝手にサムネイルにしてくれたら楽だと思います。その方法をご説明します。

まず、記事のオブジェクトを引数にとると、メインの画像のパスを返してくれるヘルパーメソッドを作ります。ヘルパーメソッドはconfig.rb内で、helpers doの中で定義することができます。


Nokogiriというライブラリでhtmlをパースし、最初に出てくるimgタグのsrc属性を取得しています。また画像を使っていない場合や、外部サイトの画像を使っている場合には、空白用の画像のパスを返すようにしています。

View側では下のように、記事のオブジェクトを引数にして使います。

スポンサーリンク

記事内の画像が表示されなくなってしまう場合

記事をKramdownというMarkdownパーサーを使っている場合などに、上の手順を行うと記事内の画像が表示されなくなる場合があります。

Kramdownだと下のように相対パスを指定した場合、current_articleからの相対パスと解釈してくれて適切なパスに変換してくれます。


下のように適切なパスを出力してくれる。


ですが、上の手順で、記事の一番上の画像のパスを取り出す処理にて、対象の記事がcurrent_articleでない時に、記事を生成することになります。生成される画像のパスは下のようにサイト全体のimagesディレクトリからの相対パスにしてしまいます。


その記事のURLにアクセスした時に、current_articleがその記事になるので適切に生成し直してくれるのでは?と思うかもしれませんが、一度生成された記事はキャッシュの中に残りそれが出力されてしまいます。Middlemanではキャッシュのクリアを任意にすることができないようです。

なので、記事を表示するテンプレートにて、適切なパスに置換する処理を加えます。まずヘルパーメソッドに下のように追記します。


記事を出力するView側にて下のようにします。


また、この問題が発生している人は、先ほど作ったmain_img_path内で取得するパスもおかしい可能性が高いです。main_img_path内でもrender_with_correct_imgを使って下のように修正します。2行目が修正されています。

100px以下のサイズを指定するとエラーが起きる

これは自分のパソコンだけかもしれませんが、resize_toで100以下を指定すると、次のようなエラーが発生しました。


なので、小さくても150程度にし、さらに小さくしたい場合はcss側で調整するようにしたほうがいいです。

build時に元ファイルに更新があったものだけ作り直すようにする

build時に全サムネイルを作り直します。しかも、同じサムネイルファイルでも複数箇所から呼び出している場合、その回数分生成し直すという原始的な仕様なので非常に時間がかかります。

なので、毎回全サムネイルを作る直すのをやめ、サムネイルと元ファイルのタイムスタンプを保存する管理ファイルを作り、元ファイルのタイムスタンプが変更された場合にのみ、一度だけ生成するように細工をしました。

まず、config.rbに次のコードを入れ、middleman build --cleanとオプションをつけないとサムネイルを削除しないようにします。デフォルトだと逆で、--no-cleanとつけて削除しないようになっています。


そして、config.rbからclass_evalを使うことで、gemを直接修正しなくても挙動を変えることが可能です。元ファイルから問題のinitializeメソッドをまるまるコピーし、コードを追加しています。


※ middleman-simple-thumbnailer (1.0.2)の場合

ちなみに、config.rbの追記する場所は、acitivateする次の部分より上に書かないと反映されません。


これで大幅にbuild時間が短くなりました。

middleman-s3_syncでサムネイル画像を同期してくれない

Amazon S3を利用していて、ファイルの同期にmiddleman-s3_syncというgemを使っている場合は、デフォルトだとサムネイル画像は同期してくれません。

こちらもconfig.rbに細工することで同期することが可能です。


こちらは、acitvate :s3_syncよりも上に追記してください。

"**/*.300.jpg", "**/*.150.jpg"という部分はサムネイルのファイル名をワイルドカードで指定しています。ファイル名の数字の部分はご自身の使い方で変わるので適宜修正してください。

さいごに

いかかでしたでしょうか?きれいにサムネイルを表示できましたでしょうか?

ちなみに、この作業で使ったそれぞれのライブラリのバージョンは以下です。

ライブラリ名 バージョン
middleman-core 3.4.0
middleman-blog 3.6.0.beta.2
middleman-simple-thumbnailer 1.0.2
middleman-s3_sync 3.3.4