【 Cocoon 】AMP で画像拡大表示のライトボックスを実装する方法

amp-image-lightboxを使いCocoonに画像拡大を実装

Akira

福岡在住ウェブデザイナー。Web サイト制作に役立つ情報を「見やすさ」と「使いやすさ」にこだわり紹介しています。

WordPress テーマ「 Cocoon 」の AMP ページに、画像の拡大表示を実装する方法のご紹介です。

実際の動作は、下の GIF でご確認いただけます( PC でご覧の場合には、 GIF の Setting より高画質に変更できます)。

画像をクリックすると、ページを移動せず、コンテンツを覆うように拡大します。また、背景は暗くなります。

その暗い背景をクリック・タップをすると、元に戻ります。

多くのサイトが導入している Lightbox とほぼ同じ動作です。ただし、スライドショーの機能はありません。

使用する AMP スクリプトは、 amp-image-lightbox

基本的に 3 ステップ、かつ 100% コピペでカスタマイズは完了します。

拡大対象の画像

今回のカスタマイズで拡大可能になる画像は、 URL に wp-content/uploads が含まれた <a> タグで囲まれ、さらに <p> タグで囲まれた <amp-img> です。

<p>
  <a href="サイトURL/wp-content/uploads/〜">
    <amp-img src="#" alt="" width="" height="" layout=""></amp-img>
  </a>
</p>

想定しているのは、「メディアを追加」から「リンク先」を「メディアファイル」で埋め込んだ投稿本文内の画像です。

ただ、サイトによって画像の埋め込み方法は異なるため、保証はできません。

対象を制限しているのは、アフィリエイトバナーなどの画像が拡大すると、意図しない動作になるためです。

それでは、実装方法をご説明します。

amp-image-lightbox スクリプトの読み込み

まず行うことは、 amp-image-lightbox スクリプトの読み込みです。

子テーマの tmp-user/amp-head-insert.php に、下記の <script> タグを追加します。

<script async custom-element="amp-image-lightbox" src="https://cdn.ampproject.org/v0/amp-image-lightbox-0.1.js"></script>

amp-image-lightbox タグの設置

次に、 <amp-image-lightbox> タグを設置します。

子テーマの tmp-user/amp-footer-insert.php に、下記の <amp-image-lightbox> タグを追加します。

<amp-image-lightbox id="amp-lightbox" layout="nodisplay"></amp-image-lightbox>

amp-img の置換

amp-image-lightbox は、 <amp-img> タグに必要な属性を追加することで動作します。

子テーマの functions.php に下記のコードを追加し、必要な属性を追加する置換処理をします。

// 独自の AMP 用へのコンテンツ置換
function my_convert_content_for_amp( $the_content ) {
    if( is_amp() === false ) {
        return $the_content;
    }
    
    // amp-img を amp-image-lightbox 用に置換
    $pattern     = '/<p><a href="[^"]+?\/wp-content\/uploads.+?"><amp-img(.+?)><\/a><\/p>/i';
    $append      = '<p><amp-img on="tap:amp-lightbox" role="button" tabindex="0"$1></p>';
    $the_content = preg_replace( $pattern, $append, $the_content );
    
    return $the_content;
}

// AMP 化処理
function html_ampfy_call_back( $html ) {
    if( is_admin() ) {
        return $html;
    }
    
    if( !is_amp() ) {
        return $html;
    }
    
    global $post;
    
    $transient_id    = TRANSIENT_AMP_PREFIX.$post->ID;
    $transient_file  = get_theme_amp_cache_dir().$transient_id;
    $file_path_cache = get_transient( $transient_id );
    
    if( $file_path_cache && DEBUG_CACHE_ENABLE ) {
        if( file_exists( $transient_file ) ) {
            $html_cache = get_file_contents( $transient_file );
            if( $html_cache ) {
                return $html_cache;
            }
        }
    }
    
    $head_tag = null;
    $body_tag = null;
    $style_amp_custom_tag = null;
    
    if( preg_match( '{<!doctype html>.+</head>}is', $html, $m ) ) {
        if( isset( $m[0] ) ) {
            $head_tag = $m[0];
        }
    }
    
    if( preg_match( '{<body .+</html>}is', $html, $m ) ) {
        if( isset( $m[0] ) ) {
            $body_tag = $m[0];
        }
    }
    
    if( preg_match( '{<style amp-custom>.+</style>}is', $head_tag, $m ) ) {
        if( isset( $m[0] ) ) {
            $default_style_amp_custom_tag = $m[0];
            $dieted_style_amp_custom_tag  = get_dieted_amp_css_tag( $default_style_amp_custom_tag, $body_tag );
            
            $head_tag = str_replace( $default_style_amp_custom_tag, $dieted_style_amp_custom_tag, $head_tag );
        }
    }
    
    if( $head_tag && $body_tag ) {
        $body_tag = convert_content_for_amp( $body_tag );
        // 独自の置換処理で body タグ内を AMP 化
        $body_tag = my_convert_content_for_amp( $body_tag );
        $html_all = $head_tag . $body_tag;
        
        $is_include_body = includes_string( $html_all, '</body>' );
        if( $is_include_body && DEBUG_CACHE_ENABLE ) {
            set_transient( $transient_id, $transient_file, DAY_IN_SECONDS * 1 );
            put_file_contents( $transient_file, $html_all );
        }
        
        return $html_all;
    }
    
    return $html;
}

amp-image-lightbox の動作に必要な属性を追加しつつ、 <amp-img> の親要素の <a> タグを削除しています。これは、画像が <a> タグで囲まれていると、 amp-image-lightbox が動作しないためです。

これで、基本的な実装は完了です。

尚、 amp-image-lightbox はキャプションを表示できますが、今回の置換処理はキャプションは考慮していません。

function.php に追加するコードの注意点

function.php に追加するコードには、注意点が 1 つあります。

それは、親テーマの lib/amp.php で定義してある html_ampfy_call_back() 関数を使っていることです。

今後の Cocoon のアップデートで html_ampfy_call_back() 関数が変更された場合には、ご自身で変更に対応しなければなりません。

ご自身での対応に不安がある場合には、今回のカスタマイズはおすすめしません。

必要であれば CSS を指定

amp-image-lightbox は、基本的に CSS の指定は不要です。

ただ、必要に応じて、子テーマの amp.css に CSS を指定します。

マウスカーソルの形状

マウスポインターが画像の上にある時に、マウスカーソルの形状が変化すると、瞬時に拡大可能だと分かります。

下記の CSS を指定すると、マウスカーソルの形状が + アイコン付きの虫眼鏡に変化します。

amp-img[role=button] {
  cursor: zoom-in;
}
ホバーで虫眼鏡を確認

拡大時の背景色

画像拡大時の黒い背景色は変更できます。

初期値は下記のとおりです。必要であれば、 background の値を変更します。

amp-image-lightbox {
  background: rgba(0, 0, 0, .95);
}

z-index

<amp-image-lightbox> タグには、自動的に CSS の z-index: 1000; が指定されます。

この値より大きな z-index を指定した要素は、拡大時の画像に被ってしまいます。被る要素がある場合には、下記のように値を変更します。

amp-image-lightbox {
  z-index: 199999;
}

小さなサイズの画像を使う場合

amp-image-lightbox は、画像サイズに関係なく、画像を画面いっぱいに拡大します。

そのため、画面サイズが大きな PC での拡大時に、小さなサイズの画像は荒くなります。

PC でも画像をきれいに見せたい場合には、 CSS で画像の最大サイズを指定します(ただし、この方法は画像位置に難あり)。

amp-image-lightbox img {
  max-height: 450px;
  max-width: 800px;
}

もしくは、大きなサイズの画像をアップロードした上で、 <amp-img> に srcset 属性をつけます。

ただ、 AMP ページへのアクセスがスマホからのみの場合には、対策は必要ないかなとは思います。

対策が必要なケースは、 AMP ページに PC からのアクセスが多い場合、または Cocoon をゴリゴリ改造して Canonical AMP ( AMP ページしかないサイト)にしている場合です。


今回ご紹介した amp-image-lightbox は、 Simplicity でも実装できます。

Cocoon とは実装方法が異なるため、 Simplicity での実装をご希望の場合には「 Simplicity でのやり方を教えろ!」とコメントをください。ご要望があれば、なるべく急いで記事を作成します。