AMPで「ページトップへ遷移する」ボタンを設置する方法

これまでの普通のサイトだったら、何も考えずにjsでサクッと実装できること。
しかし、AMPではすんなり実装ができなかったりします。

それは、AMPはサードパーティーのjsが使えない ためです。
つまり、自分でjsを書くことや、外部ライブラリを読み込んだりすることができません。

「つ、つらい・・・😢」
そんな風なイメージをお持ちの方も、多いのではないでしょうか。

が、心配には及びません。
AMPには、そんな機能を簡単に実装することができる、コンポーネントが用意されています。

この記事では、実装の仕方の解説や、実装中に気になったことをお伝えします。

AMPのオフィシャルでは実装手順を紹介しています。
順に進めていくことで、簡単に実装ができます。
Example: Scroll to top - amp.dev

また、実装サンプルを紹介しているページもあり、これも参考にすると良いです。
AMP Playground

  1. AMPサイトで「ページトップへ移動するボタン」を実装する方法
  2. amp-position-observerとamp-animation、二つのコンポーネントを使う
  3. Nuxt.jsでダブルクォートがhtmlエンティティに変換されてしまった
  4. まとめ:AMPコンポーネントの実装は超簡単

何がいいって、単にコピペをしていけば動くところです。
すでにコンポーネント化されている機能であれば、実に手軽に実装が完了します。

ついでにといってはあれですが、実装時にNuxt.jsでうまく行かなかったHTMLエスケープの問題を解決したので、そのことも書いてあります。

AMPサイトで「ページトップへ移動するボタン」を実装する方法

Scroll to Topとは、ページトップへ移動するボタンです。
画面の右下や、左下にあるものです。
様々なサイトで、よく見かけるごく一般的なUIですね。

必ずしも必要なものではないのですが、サイトのデザインによっては、ユーザーの利便性の向上を測ることができます。

このブログでは、一度実装してはみたものの、外しました。
理由はヘッダーが追従してくるので、ユーザーがトップに戻ることで得られるベネフィットが、それほど多くないと判断したからです。
画面の下側にあるということは、スマートフォンでは不用意にタップしてしまう要因にもなり得ることと、文章を読む上で邪魔に感じる場合もあると考えたからです。
(本来ならちゃんとユーザー調査しなければいけませんね)

amp-position-observerとamp-animation、二つのコンポーネントを使う


今回はAMPが用意するコンポーネントを2つ読み込みます。

amp-position-observer

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

☝️訳あって、このsrc=以降のリンクをシングルクォートで囲んでいます。
正式にはダブルクォートになっています 🙏

amp-position-observerはユーザーの スクロール位置を監視して特定の位置でトリガー させるのに使うコンポーネントです。
スクロールと連動した、Fade-inとかParallaxなどのインタラクションは、amp-fx-collection コンポーネントで実装できます。

フェードやパララックスをAMPブログに実装できるamp-fx-collection
AMPの為に用意されたコンポーネントを使用することで、フェードイン・アウトやパララックスなどのスクロール・エフェクトが簡単に実装できます。ここではその方法をサラリと紹介していきます。...

amp-animation

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

amp-animationは文字通り、アニメーションの詳細を制御 するのに使うコンポーネントです。

Web Animations API を使用してアニメーションを実現しているとのこと。

Web Animations APIがわからないので調べてみました。
互換性抜群!「Web Animations API」の基本をおさらいしよう|ferret フェレット

現在はjsやらcssやら色んな方法がありすぎるアニメーションの実装に、標準となる仕様を作って、安全かつ効率的に使っていきましょうということでしょうか。

アニメーションの負荷

そういえばアニメーションを実装するとなると負荷が気になりますね。

「jsとcssのどっちが負荷が少ないのか」
そんな風に考えていたのです。
しかし、どちらが正しいみたいなことはないようです。
CSS アニメーションと JavaScript のアニメーションの比較  |  Web |  Google Developers

とりあえずはWeb Animations APIに即した形を目指してみたいと思います。

Nuxt.jsでダブルクォートがhtmlエンティティに変換されてしまった

アニメーションを定義する記述をexampleからコピペしました。

<amp-animation id="showAnim" layout="nodisplay">
    <script type="application/json">
      {
        "duration": "200ms",
        "fill": "both",
        "iterations": "1",
        "direction": "alternate",
        "animations": [{
          "selector": "#scrollToTopButton",
          "keyframes": [{
            "opacity": "1",
            "visibility": "visible"
          }]
        }]
      }
    </script>
  </amp-animation>

このままビルドするとブラウザでエラーが出てしまいました。
原因は、scriptタグの中の、ダブルクォートがHTMLエンティティに自動的に変換 されてしまっていました。
直接書いてしまうと、エスケープする処理が走るようですね。

解決方法

と、いうわけで、この部分の記述を変数に押し込めて、v-htmlで表示させることにしました。
この方法であれば、変数内の文字列はhtmlとしてそのまま吐き出してくれるようです。

~/components/ScrollToTop.vue

<template lang="pug">
  .scroll_to_top
    amp-animation#showAnim(layout='nodisplay')
      script(type="application/json" v-html='show_arrow')

    amp-animation#hideAnim(layout='nodisplay')
      script(type='application/json' v-html="hide_arrow")

    #marker
      amp-position-observer(on='enter:hideAnim.start; exit:showAnim.start', layout='nodisplay')

    button#scrollToTopButton.scrollToTop(on='tap:top-page.scrollTo(duration=200)')

</template>
<script>
  export default {
    data() {
      return {
        show_arrow: '{"duration": "200ms","fill": "both","iterations": "1","direction": "alternate","animations": [{"selector": "#scrollToTopButton","keyframes": [{"opacity": "0.6","visibility": "visible"}]}]}',
        hide_arrow: '{"duration": "200ms","fill": "both","iterations": "1","direction": "alternate","animations": [{"selector": "#scrollToTopButton","keyframes": [{"opacity": "0","visibility": "hidden"}]}]}'
      }
    }
  }
</script>

ちなみに、一つのコンポーネントにまとめても動きました。
ページのどの部分に設置しても、動作させられそうです。

まとめ:AMPコンポーネントの実装は超簡単


AMPコンポーネンツを使うメリットは、簡単さです。
ドキュメント通りにコピペしたら、実装完了してしまう手軽さ。

jQueryを使ったりするより、遥かに楽です。
それは、AMP専用のコンポーネントゆえに、設定などに手間取らないことです。

また、サンプルもあったりするので、分かりやすい。
こういうところに、実装のハードルを下げようという心意気が伝わってきますね。

いろいろな機能を持ったコンポーネントが、既に用意されています。
これらを活用したら、大概のやりたい事は実現できそうです。

#amp
#nuxt
ChaosBoy

テーマは「脱・思考停止」。
コメントはtwitterでお気軽に。