AMP

2020.09.09

AMP対応|プラグインなしで記事内の目次

AMP化しても記事目次のプラグイン「TOC+」「Easy Table of Contents」は機能していましたが、javascriptのエラーが出て、気になるのでプラグインなしで参考になるものを探しました。

AMP対応のスムーススクロールする目次

ラムネグさんのコードを元に見出しへのアンカーリンクをscrollToに変更したり、amp-position-observerを設置したり、AMPに対応させました。

function.php AMP用

function add_mokuji($content){
  
  $threshold = 2; //見出しが2つあれば、目次を表示
  
  if( preg_match_all('/<h([23])>(.*?)<\/h\1>/u', $content, $matches,  PREG_SET_ORDER) ){
    if( count($matches) >= $threshold ){
    
      $link_no = 1;
      $mokuji_title = '<div id="toc-container"><p class="toc-title">この記事の目次</p>';
      $mokuji = '<ol>';
      $prev_level = 2;
      
      foreach( $matches as $m ){
        $level = $m[1];
        $text = $m[2];
        
        if($level == 3 && $prev_level == 2){
          $mokuji .= '<ol class="indent">';
        }
        
        if($level == 2 && $prev_level == 3){
          $mokuji .= '</ol>';
        }
        // scrollToでスムーススクロール 要AMP JS
        $mokuji .= '<li><a on="tap:jump-' . $link_no . '.scrollTo(duration= 300)">' . $text . '</a></li>';
        
        $link_no++;
        $prev_level = $level;
      }
      
      if($prev_level == 3){
        $mokuji .= '</ol>';
      }
      $mokuji .= '</ol>';
      // amp-position-observer を設置。目次が画面から消えたら「目次へ戻る」ボタンを表示
      $button_target .='<div class="button-target toc"><amp-position-observer on="enter:hideButton.start; exit:showButton.start" layout="nodisplay"></amp-position-observer></div></div>';
           
      $content = preg_replace('/(\s)(<h[23]>.*?<\/h)/u', "$1$mokuji_title$mokuji$button_target$2", $content, 1);
      
      /* 見出しにID付け */
      $h_no = 1;
      $content = preg_replace_callback(
        '/<h([23])>(.*?)<\/h\1>/u',
        function($matches) use(&$h_no){
          return '<h' . $matches[1] . ' id="jump-' . $h_no++ . '">' . $matches[2] . "</h$matches[1]>";
        },
        $content
      );
    }
  }
  
  return $content;
}
add_filter('the_content', 'add_mokuji');
?>

目次が消えたら「目次へ戻る」ボタンを表示

目次にamp-position-observerに設置して画面から目次が消えたら「目次へ戻る」を表示するようにしました。

詳しくはこちら

amp-position-observeramp-animation、2つのコンポーネントを読み込みます。
※WordpressのAMPプラグイン使用している場合はすでに読み込まれています。

header.phpに追加

<!-- amp-position-observerの読み込み -->
<script async custom-element="amp-position-observer" src="https://cdn.ampproject.org/v0/amp-position-observer-0.1.js"&gt;&lt;/script>
<!-- amp-animationの読み込み -->
<script async custom-element="amp-animation" src = "https://cdn.ampproject.org/v0/amp-animation-0.1.js"&gt;&lt;/script>

ボタンの表示非表示のアニメーションの設定です。<body>直下に記述します。

body直下に追加

<!-- ボタンを表示するアニメーション -->
<amp-animation id="showButton" layout="nodisplay">
<script type="application/json">{
    "duration": "200ms",
    "fill": "both",
    "iterations": "1",
    "direction": "alternate",
    "animations": [
        {
        "selector": "#pagetop",
        "keyframes": [
            { "opacity": "1", "visibility": "visible" }
        ]}
]}
</script>
</amp-animation>
<!-- ボタンを消すアニメーション -->
<amp-animation id="hideButton" layout="nodisplay">
<script type="application/json">{
    "duration": "200ms",
    "fill": "both",
    "iterations": "1",
    "direction": "alternate",
    "animations": [
        {
        "selector": "#pagetop",
        "keyframes": [
            { "opacity": "0", "visibility": "hidden" }
        ]}
]}
</script>
</amp-animation>

ボタンの記述はfixedさせるので、どこでもOK。「ページトップに戻る」だとフッターの後に記述することが多いので同じ位置に。

footer.php

<p id="pagetop">
  <a id="page-top" on="tap:toc-container.scrollTo(duration = 300)" class="back-toc">目次へ戻る</a>
</p>