画像を利用した記事を作成しレビューに出すと、以下のような指摘が来たことはないでしょうか?
アップロードする画像の解像度や表示サイズにもよるのですが、現状PowerCMS Xのリッチテキストエディタで画像挿入した際、高精細なディスプレイで閲覧した時に写真がぼやけると言われる、逆に高精細ではない普通のディスプレイに必要以上の解像度の画像を送信している可能性があります。2018年6月の社内会議で私が話したのですが、「レスポンシブ画像」で解決したいと考えていました。当ブログでは(個人サイトでも)手動でレスポンシブ画像を用意しているのですが、できれば自動化してさまざまなユーザーにレスポンシブ画像を用意(解像度の切り替えを実現)してもらいたいと考えます。
レスポンシブ画像の提供についてはChromeに同梱されているLighthouseでもチェックすることができるようになっており(Best PracticeのServes images with appropriate resolution)、解説ドキュメントがweb.devの「レスポンシブ画像を提供する」で公開されています。
レスポンシブ画像の提供をサポートするプラグイン
少し試してみました。まずプラグインでpre_insert_assetコールバックに対する処理を書きます。表示させたい幅の2倍・3倍の幅を持つ画像を用意してテンプレート変数に値を追加する処理です。
private function image_width_is_equal_or_min( $original_width, $create_width ) {
if ( $original_width <= $create_width ) {
return true;
} elseif ( $original_width + 1 <= $create_width ) {
return true;
} elseif ( $original_width - 1 <= $create_width ) {
return true;
}
return false;
}
public function pre_insert_asset( $cb, $app, $insert_assets, &$loop_vars ) {
$max_ratio = 3;
for ( $i = 0, $n_vars = count( $loop_vars ); $i < $n_vars; $i += 1 ) {
$obj = $insert_assets[ $loop_vars[$i]['id'] ];
if ( $obj->class !== 'image' ) {
continue;
}
$assetproperty = $app->get_assetproperty( $obj, 'file' );
$original_width = $assetproperty['image_width'];
for ( $j = 2; $j <= $max_ratio; $j += 1 ) {
$url = '';
$create_width = $loop_vars[$i]['width'] * $j;
if ( $original_width > $create_width ) {
$args = [ 'width' => $create_width ];
$url = PTUtil::thumbnail_url( $obj, $args, $assetproperty );
$loop_vars[$i]["url_${j}x"] = $url;
$loop_vars[$i]["width_${j}x"] = $create_width;
} elseif ( $this->image_width_is_equal_or_min( $original_width, $create_width ) ) {
$url = $loop_vars[$i]['permalink'];
$loop_vars[$i]["url_${j}x"] = $url;
$loop_vars[$i]["width_${j}x"] = $original_width;
break;
}
}
}
}
次にリッチテキストエディタに挿入される際のimg要素のテンプレートがtmpl/insert_asset.tmpl
にあるので、alt-tmpl/insert_asset.tmpl
にコピーしimg要素にsrcset属性・sizes属性を加えます。13行目付近です。
src="<mt:var name="url" escape>"
<mt:if name="url_2x">
srcset="<mt:var name="url" escape> <mt:var name="width" escape>w, <mt:var name="url_2x" escape> <mt:var name="width_2x" escape>w"
sizes="(min-width: <mt:var name="width" escape>px) <mt:var name="width" escape>px, 100vw"
</mt:if>
カスタマイズ後に表示させたい幅の2倍以上の幅を持つ画像をアップロードするのですが、その際「サムネイルを利用」にチェックを入れて表示させたい幅を指定します。その結果、以下のようなimg要素が挿入されるようになり、スロットサイズに応じた適切な画像が読み込まれるようになりました。例えば高精細なディスプレイでは画像がきれいに表示されるようになりますし、高精細ではない普通のディスプレイではよりサイズの小さい画像ファイルを用いて表示されます。(実際にはそう単純ではないのですが、ここでは簡易な説明に留めます。詳細は「レスポンシブ画像 - ウェブ開発を学ぶ | MDN」をご覧ください。)
<!-- 1枚目: 1200pxの画像をアップロードし、200pxで表示する -->
<img src="/assets/thumbnails/thumb-200xauto-551-file.jpg" sizes="(min-width: 200px) 200px, 100vw" srcset="/assets/thumbnails/thumb-200xauto-551-file.jpg 200w, /assets/thumbnails/thumb-400xauto-551-file.jpg 400w" alt="" width="200" height="300" />
<!-- 2枚目: 800pxの画像をアップロードし、400pxで表示する -->
<img src="/assets/thumbnails/thumb-400xauto-549-file.jpg" sizes="(min-width: 400px) 400px, 100vw" srcset="/assets/thumbnails/thumb-400xauto-549-file.jpg 400w, /assets/entry/443/pic_edamame.jpg 800w" alt="" width="400" height="267" />
<!-- 3枚目: テンプレートを3倍サイズまで対応させた上で533pxの画像をアップロードし、250pxで表示する -->
<img src="/assets/thumbnails/thumb-250xauto-551-file.jpg" sizes="(min-width: 250px) 250px, 100vw" srcset="/assets/thumbnails/thumb-250xauto-551-file.jpg 250w, /assets/thumbnails/thumb-500xauto-551-file.jpg 500w, /assets/entry/445/pic_sample_03.jpg 533w" alt="" width="250" height="375" />
このコードでさまざまなWebサイトに対応できるのか、ベストな設定が記述できているのかは検証の必要がありますが(おそらくサイト・コンポーネント毎に細かく定義する必要があるのではないかと考えます)、PowerCMS X本体を直接カスタマイズすることなくsrcset・sizes属性をつけることが可能であることが分かりました。余談になりますがloading="lazy"
も付けることができるでしょう。
WebP形式のファイルに対応する
ImageWebPプラグインが有効化されている場合、先に紹介したコードで生成されたサムネイルについてもWebP形式のファイルが生成されています。サイトルートの.htaccess
に「WebP images with htaccess」で紹介されているリライトルールを追加しておくことで、ユーザーエージェントがWebP形式に対応している場合はWebP形式のファイルが送信されるようになります。