Hugo: 画像のサムネイルとEXIF表示ショートコード
本サイトはフォトブログである。2021/06/01現在、このサイトは『Future Imperfect Slim』というテーマを選択しているが、このテーマはフォトブログに特化したつくりではないため、写真の取り扱いに不足が感じられた。それをshortcodeで補おうと思う。
本サイトはフォトブログである。2021/06/01現在、このサイトは『Future Imperfect Slim』というテーマを選択しているが、このテーマはフォトブログに特化したつくりではないため、写真の取り扱いに不足が感じられた。それをshortcodeで補おうと思う。
フォトブログならではの画像データへの要求・・・ というよりは、私が考えるフォトブログへの要求を以下に記載してみよう。
- 通常はサムネイル表示で、クリックすると元データ、という作りとしたい
- ブログである以上、記事を素早く読みたいから
- だが写真を見るときは元データあるいはそれに近い高解像度データが見たい
- EXIFデータが付与されていると嬉しい
- 写真はどんな条件で撮られたか気になる
本記事はこれらを実現するために作成したshortcodeを紹介する。
利用例
まず最初に、記事内でのshortcodeの使い方は紹介する。
{{< photo src="images/hoge.jpg" title="fuga" >}}
記事内のファイル(Page Resources)のパスとタイトルを付けるだけというシンプル構成だ。
出力はこうなる。
shortcode実装
実装は以下のようなコードとなっている。 (/layouts/shortcodes/photo.html)
{{- $imageName := .Get "src" -}}
{{- $title := .Get "title" | default "" -}}
{{- $originalImage := (.Page.Resources.ByType "image").GetMatch (printf "**%s**" (.Get "src")) -}}
{{- $image := $originalImage.Resize "1920x" -}}
{{- $noExif := .Get "noExif" -}}
{{- $sizeInMB := div (len $originalImage.Content) 1048576.0 -}}
<div class="photo">
<figure>
<a href="{{$originalImage.RelPermalink}}">
<img src="{{$image.RelPermalink}}" alt="{{ .Get "alt" }}" loading="lazy"/>
</a>
{{ if (and $originalImage.Exif (ne $noExif "true")) }}
<figcaption>
{{ if (ne $title "") }}
<p>
{{ $title }}
</p>
{{ end }}
{{ with $originalImage.Exif }}
<p class="exifTags">
{{ if .Tags.Model }}
<span class="exifElement">
<i class="fa fa-camera"></i>
{{ .Tags.Model }}
</span>
{{ end }}
{{ if .Tags.LensModel }}
<span class="exifElement">
with {{ .Tags.LensModel }}
</span>
{{ end }}
/
{{ if .Tags.FocalLength }}
<span class="exifElement">
{{ .Tags.FocalLength }} mm
</span>
{{ end }}
{{ if .Tags.ExposureTime }}
<span class="exifElement">
, {{ .Tags.ExposureTime }}
</span>
{{ end }}
{{ if .Tags.FNumber }}
<span class="exifElement">
, f/{{ .Tags.FNumber }}
</span>
{{ end }}
{{ if .Tags.ISOSpeedRatings }}
<span class="exifElement">
, ISO{{ .Tags.ISOSpeedRatings }}
</span>
{{ end }}
{{ if and .Tags.GPSLatitude .Tags.GPSLongitude }}
{{ $latSign := 1 }}
{{ if eq .Tags.LatRef "S" }}
{{ $latSign = -1 }}
{{ end }}
{{ $lonSign := 1 }}
{{ if eq .Tags.LonRef "W" }}
{{ $lonSign = -1 }}
{{ end }}
{{ $lat := mul $latSign (add (index .Tags.GPSLatitude 0) (add (div (index .Tags.GPSLatitude 1) 60) (div (index .Tags.GPSLatitude 2) 3600))) }}
{{ $lon := mul $lonSign (add (index .Tags.GPSLongitude 0) (add (div (index .Tags.GPSLongitude 1) 60) (div (index .Tags.GPSLongitude 2) 3600))) }}
<span class="exifElement">
taken
<a href="http://www.openstreetmap.org/?mlat={{ $lat }}&mlon={{ $lon }}&zoom=16&layers=M">
<i class="fa fa-map-marked"></i>
here
</a>
</span>
{{ end }}
({{ printf "%.1f" $sizeInMB }} MB)
</p>
{{ end }}
</figcaption>
{{ end }}
</figure>
</div>
EXIF周りはこちらを参考にさせてもらいました。ありがとうございます。
この実装では横幅1920pxに変換しているので、サムネイルとしてはかなり大きめだ。とりあえずこんなサイズで始めているが、微調整が必要だろうとは思っている。この実装、PCとSPを区別していないあたりはまだまだ雑な実装である。ちゃんとレスポンシブ対応にするともっと良いのだろう。
これを書きながら写真の扱いに関してはHugoのメリットを存分に感じられた。リサイズ≒サムネイル生成も簡単だし、変換方式も柔軟だし、もしクロップするなら「Smart」クロップ方式が選択できる。EXIF情報の取得に標準で対応しているのも嬉しい。
もっと良い実装ができたら、是非ネットに公開して共有していただきたい。