[a-blog cms]一つのユニットで、PCとスマホの画像出しわけをする


a-blog cmsアドベントカレンダー2018の2日目のエントリーです。


JavaScriptを使わず、ユニット一つだけで状況に応じて違う画像を出す方法を考えてみます。
使用場面としては、横に長い図のように、スマートフォンなど画面幅が狭い端末では見づらい画像を、縦長に描き直した別の図に差し替え表示するときなどを想定しています。
a-blog cms2.8系以降でテストしています。
大まかな手順は以下の通り。

  1. メディアユニットを拡張する
  2. ファイル名を書き換える校正オプションを作る
  3. 拡張ユニットを登録する

実装(解説は後述)

メディアユニットを拡張する

/a-blog cmsのインストールディレクトリ/themes/自分のテーマ/include/unit/extend.html
を作成して、拡張するメディアユニットの内容を記述。

<!-- BEGIN unit#media_swap -->
<!-- media_swap -->
<div class="column-media-{align}{display_size_class}"{display_size}[raw]><!-- BEGIN type#image -->
	<!-- BEGIN link#front -->
	<a href="{url}"{viewer}[raw]><!-- END link#front -->
		<picture>
			<source media="(min-width: 768px)"
			srcset="%{HTTP_ROOT}{path}">
			<source media="(min-width: 320px)"
			srcset="%{HTTP_ROOT}{path}[filenameExtend('-sp')]">
			<img src="%{HTTP_ROOT}{path}" alt="{alt}" width="{x}">
		</picture><!-- BEGIN link#rear -->
	</a><!-- END link#rear --><!-- BEGIN_IF [{caption}[delnl]/nem] -->
	<p class="caption">{caption}[nl2br]</p><!-- END_IF --><!-- BEGIN text:veil -->
	<p class="">{text}</p><!-- END text:veil -->
	<!-- END type#image -->
</div>
<!-- END unit#media_swap -->

ファイル名を書き換える校正オプションを作る

/a-blog cmsのインストールディレクトリ/extension/acms/Corrector.php
に、オリジナルの校正プションを追記する。

    public function filenameExtend($filepath, $extend)
    {
		$pathinfo = pathinfo($filepath);
		$dir = $pathinfo["dirname"];
		$name = $pathinfo["filename"];
		$extention = $pathinfo["extension"];
		return $dir."/".$name.$extend[0].".".$extention;
    }

拡張ユニットを登録する

コンフィグ>編集設定に、拡張ユニットを登録



コンフィグ>ユニット設定に、ユニットの初期表示を登録



解説


元画像が同じであれば、large画像を保存してくれる画像ユニットでも行けそうですが、全く違う画像を出したいため、任意のファイル名で画像を指定できるメディアユニットを拡張します。

メディアユニット
メディアユニットとはメディア管理ページでアップロードした画像やPDFを挿入するためのユニットです。(中略)エントリー編集画面のユニット追加ボタンからメディアを選択すれば画像やPDFを挿入できます。

ユニットの拡張というとなんだか身構えてしまいますが、ユニットのテンプレートを新しく作る、と考えるとわかりやすいです。
ユニットが持っている変数は変えられないので、出力の形を任意に変えてやる作業です。

ユニットの拡張機能
ユニットの拡張機能をつかえば、デフォルトで出力されるエントリーのテキストユニットや画像ユニットに足りないHTMLやCSSを補うことが出来ます。

拡張するユニットのテンプレートを作る


まず、使用中のテーマディレクトリに、拡張ユニット用のファイルを作成します。
/a-blog cmsのインストールディレクトリ/themes/自分のテーマ/include/unit/extend.html
このファイルの中に、オリジナルのメディアユニットのテンプレートをコピペします。

オリジナルのメディアユニットのテンプレートは、
/a-blog cmsのインストールディレクトリ/themes/system/_layouts/unit.html
にあります。今回引用するのは、<!-- BEGIN unit#media -->から<!-- END unit#media -->の部分。
これを、先程作ったextend.htmlにコピペします。

<!-- BEGIN unit#media -->
@section(media-unit)
<!-- media -->
<div class="column-media-{align}{display_size_class}"{display_size}[raw]><!-- BEGIN type#image -->
	<!-- BEGIN link#front -->
	<a href="{url}"{viewer}[raw]><!-- END link#front -->
		<img class="columnImage" src="%{HTTP_ROOT}{path}" alt="{alt}" width="{x}"><!-- BEGIN link#rear -->
	</a><!-- END link#rear --><!-- BEGIN_IF [{caption}[delnl]/nem] -->
	<p class="caption">{caption}[nl2br]</p><!-- END_IF --><!-- BEGIN text:veil -->
	<p class="">{text}</p><!-- END text:veil -->

	<!-- END type#image --><!-- BEGIN type#file -->

	<a href="%{HTTP_ROOT}{path}"><!-- BEGIN_IF [{thumbnail}/nem/] -->
	<img class="columnIcon" src="%{HTTP_ARCHIVES_DIR}{thumbnail}" alt="ファイルを開く" width="{x}" height="{y}"><!-- ELSE -->
	<img class="columnIcon" src="%{HTTP_ROOT}{icon}" alt="ファイルを開く" width="{x}" height="{y}"><!-- END_IF -->
	</a><!-- BEGIN_IF [{caption}[delnl]/nem] -->
	<p class="caption">{caption}[nl2br]</p><!-- END_IF --><!-- BEGIN text:veil -->
	<p class="">{text}</p><!-- END text:veil -->
	<!-- END type#file -->
</div>
@endsection
<!-- END unit#media -->

まずは、ユニット名を変更します。
メディアユニットを拡張する場合、<!-- BEGIN unit#media -->、<!-- END unit#media -->の#mediaの部分を、#media_任意の文字列に変更します。
今回は、#media_swapとしてみます。

任意のテンプレートに書き換える

メディアユニットが持っている変数を活用して、必要なテンプレートを作成します。
今回は、画像のみを想定しているので、ファイルに関する部分はとりあえず削除します。
画面幅で画像を出し分けるため、<img>ではなく、<picture>を使ったものに修正します。
修正したのがこちら。

<!-- BEGIN unit#media_swap -->
<!-- media_swap -->
<div class="column-media-{align}{display_size_class}"{display_size}[raw]><!-- BEGIN type#image -->
	<!-- BEGIN link#front -->
	<a href="{url}"{viewer}[raw]><!-- END link#front -->
		<picture>
			<source media="(min-width: 768px)"
			srcset="%{HTTP_ROOT}{path}">
			<source media="(min-width: 320px)"
			srcset="%{HTTP_ROOT}{path}">
			<img src="%{HTTP_ROOT}{path}" alt="{alt}" width="{x}">
		</picture><!-- BEGIN link#rear -->
	</a><!-- END link#rear --><!-- BEGIN_IF [{caption}[delnl]/nem] -->
	<p class="caption">{caption}[nl2br]</p><!-- END_IF --><!-- BEGIN text:veil -->
	<p class="">{text}</p><!-- END text:veil -->
	<!-- END type#image -->
</div>
<!-- END unit#media_swap -->

が、しかし、メディアユニットも画像は一つしか選択できないので、そのままでは違う画像を指定することができません。
%{HTTP_ROOT}{path}の部分が、ユニットで指定した画像のパス)
そこで、校正オプションを自作して、ファイル名を一定のルールで書き換えるようにしてみます。

校正オプション(https://developer.a-blogcms.jp/document/reference/proofreading.html)
{var}[option]というように、変数の後に[]を記述して校正オプションを使用します。また、オプションはパイプ ( | ) を使用して複数指定することもできます。

ファイル名を書き換える校正オプションを作る


メディアユニットで指定したファイル名に任意の文字列を追加して、別のファイル名にする校正オプションを作ります。
/a-blog cmsのインストールディレクトリ/extension/acms/Corrector.php
このファイル内に、新しい校正オプションを記述していきます。

校正オプションの拡張について
Acms\Custom\Correctorクラス(extension/acms/Corrector.php)にメソッドを定義することで、校正オプションの拡張が可能です。Acms\Custom\Correctorクラスが記述される、extension/acms/Corrector.phpは、アップデート時の上書き対象ではないので、自由に拡張してご利用いただけます。
    public function filenameExtend($filepath, $extend)
    {
		$pathinfo = pathinfo($filepath);
		$dir = $pathinfo["dirname"];
		$name = $pathinfo["filename"];
		$extention = $pathinfo["extension"];
		return $dir."/".$name.$extend[0].".".$extention;
    }

{ファイルのパスが入った変数}[filenameExtend("ファイル名に追加したい文字列")]
と書くことで、ファイル名に文字列を追加して展開されるようになります。
この構成をオプションを、さきほどのテンプレートに追記します。

<!-- BEGIN unit#media_swap -->
<!-- media_swap -->
<div class="column-media-{align}{display_size_class}"{display_size}[raw]><!-- BEGIN type#image -->
	<!-- BEGIN link#front -->
	<a href="{url}"{viewer}[raw]><!-- END link#front -->
		<picture>
			<source media="(min-width: 768px)"
			srcset="%{HTTP_ROOT}{path}">
			<source media="(min-width: 320px)"
			srcset="%{HTTP_ROOT}{path}[filenameExtend('-sp')]">
			<img src="%{HTTP_ROOT}{path}" alt="{alt}" width="{x}">
		</picture><!-- BEGIN link#rear -->
	</a><!-- END link#rear --><!-- BEGIN_IF [{caption}[delnl]/nem] -->
	<p class="caption">{caption}[nl2br]</p><!-- END_IF --><!-- BEGIN text:veil -->
	<p class="">{text}</p><!-- END text:veil -->
	<!-- END type#image -->
</div>
<!-- END unit#media_swap -->

2つ目の<source>タグのsrcset属性を、
{path}[filenameExtend('-sp')]
と修正しています。画面幅が狭い場合、元のファイル名に-spが付くファイルを参照するようになります(メディアユニットで指定したのがtest.pngだった場合、test-sp.pngを参照する)。

拡張したユニットを登録する

管理画面に入り、コンフィグ>編集設定と進み、「編集設定」の「ユニット追加ボタン」を編集します。
追加ボタンを押して、モードを「拡張」にして、横のらんに先程作ったテンプレートにつけた「media_swap」という名前を入力します。
ラベルは任意に設定します。



同じく管理画面のコンフィグ>ユニット設定へ進みます。
ページ最下部に、先程追加した拡張ユニットの名前がありますので、同名のボタンを押して、ユニットの入力画面を設定します。



画像をメディアに登録する

最後に、メディア管理にPC用画像とスマホ用画像を登録します。
校正オプションでテンプレートに設定したルールにしたがって、スマホ用画像は、PC用画像のファイル名に-spをつけたファイル名にして作成します。
登録したら、拡張したメディアユニットをエントリーに追加して、PC用画像を選択、保存します。

下の画像が、そのサンプルです。


HTMLだけでだいたいなんとでもなるa-blog cms


校正オプションの部分はPHPなので、そこで間違いがあると、その校正オプションを使っているページでエラーが表示されたり、画面の読み込みが途中で止まったりします。
それ以外はHTMLしかいじっていないため、少なくともサイトは動き続けます。
a-blog cmsは、だいたい何をやってもシステムまでは壊れません。
通常はテンプレート(HTML)を修正すればなんとでもなるので、トライ・アンド・エラーがしやすく、カスタマイズによるセキュリティの心配や、バージョンアップによる動作の不具合の問題もほとんどないのは、制作者としても利用者としても、メリットは大きいところだと思います。