[JavaScript]IntersectionObserverを使って、Tableに「スワイプ可能」なことを示す表示をつける方法[Grid.js]

IntersectionObserverを使って、Tableに「スワイプ可能」なことを示す表示をつける方法

今回は、以前ご紹介した
IntersectionObserver と、
最近よくご紹介しているライブラリである
Grid.js の合わせ技の記事です。

どんなものを作るかというと、次の動画をご覧ください。
こちらの動画のように、今回ご紹介するのは「Tableが画面内に入った時」「このTableはスワイプ可能です」という表示を「ふわっと出現させる」ことができる方法になります。

それでは次のセクションから、導入方法・サンプルコードなどを書いていきます。

まずはGrid.jsで、横スワイプ可能なtableをつくる

まずは、スマートフォンの画面サイズになった時、
横スワイプする事が可能なtableを、Grid.jsを使って作成してみます。

と言っても、これまでご紹介した基本形と JavaScript 側に大きな変更はありません。

Grid.jsの読み込み → html → JavaScript → cssの順で以下にサンプルを書いておきます。

Grid.jsの読み込み

これは以前の記事でも書きましたので、おさらい程度に。CDNで使うことも、CLIでインストールしてビルドすることも可能です。

CDNで使う場合は次の2行を、組み込みたいhtmlのヘッダ内で読み込みます。

[CDN経由の場合]

<link href="https://cdn.jsdelivr.net/npm/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/gridjs/dist/gridjs.umd.js"></script>

CDNで使う場合は、次を実行してインストールします。

[CLI経由の場合]

npm install gridjs --save

html部分

続いて、html側です。

[html側]

<div class="grid-wrapper">
  <div id="gridContainer" class="grid-container"></div>
</div>

↑いたってシンプルです。
html側は上記要素があれば、今回作成するTableが作れます。

JavaScript部分

続いて、JavaScript側です。

[JavaScript側]

new gridjs.Grid({
  columns: ['名前', 'ジャンル', '素晴らしさ'],
  data: [
    ['Vue', 'Frontend Framework', '★★★★★'],
    ['Vuetify', 'UI Framework', '★★★★★'],
    ['React', 'Frontend Framework', '★★★★★'],
    ['Gatsby', 'Static Site Genarator', '★★★★★'],
    ['Grid', 'Awesome Table Library', '★★★★★']
  ],
  sort: true,
  pagination: {
    enabled: true,
    limit: 3,
    summary: true,
  },
  className: {
    container: 'myContainer',
    table: 'myTable'
  },
  height: '320px',
  width: '90%'
}).render(document.getElementById('gridContainer'));

↑JavaScript側は、このように書きます。
これで、Grid.jsを使ったデータテーブルを生成することができます。

css部分

続いてcss。こちらのcssはサンプルとしての一例で、
ひとまず次のように定義しておきます。大きさ等々はお好みで。

[css側]

.myContainer {
  font-size: 1rem;
  left: 50%;
  transform: translateX(-50%);
}
table.myTable {
  max-width: initial;
  width: 500px;
}
.grid-wrapper {
  margin: 1000px auto 200px;
  position: relative;
}

↑cssは次のセクション以降でさらに追記しますが、ひとまずTable自体にはこんな感じのstyleを記述しておきます。
.grid-wrapper の上部に1000pxという、やたら大きめのmarginがついているのは、
以降のセクションで登場する、IntersectionObserber を試しやすい様に
あえてそうしています。

ここまでの記述で、次の画像のようなTableが表示できます。

Grid.jsで作成したTable

…Table自体は表示できましたが、このままでは「横スワイプできる」ということがわかりづらいですよね。そこで、次のセクションから「スワイプできますよ」という表示を作っていく、というわけです。

このTableは「スワイプ可能」です、という表示の部分をつくる

この部分は、純粋にhtmlとcssだけでできます。
htmlは、上のセクションでご紹介した
Tableを表示するために用意したhtmlに付け足す形で、次のように書きます。

[html側]

<div class="grid-wrapper is-target">
  <div id="gridContainer" class="grid-container"></div>
  <div class="swipe-able-container">
    <figure class="swipe-able-item">
      <img class="swipe-able-icon" src="./ico-swipe-able.svg" alt="swipe able">
      <figcaption class="swipe-able-text">スワイプできます →</figcaption>
    </figure>
  </div>
</div>

↑Tableを表示するために用意したhtmlに、
「このTableはスワイプ可能です」という表示を付け足した状態のhtmlです。
swipe-able-container というclassを持った部分が、付け加えた要素になります。
5行目のimg要素は指アイコンです。
これをcssアニメーションで動かして、「スワイプ可能」であることの示唆をします。
なおアイコンは、今回は こちらのサイト のアイコン素材を使用させて頂きました。(ご存知の方も多いかと思いますが、実際のWeb制作現場でもよく使用されているのを見かける有名素材サイトです)

cssは、次のように書きます。

[css側]

.swipe-able-container {
  background: rgba(0, 0, 0, 0.5);
  border-radius: 8px;
  height: 220px;
  left: 50%;
  opacity: 0;
  pointer-events: none;
  position: absolute;
  top: 50%;
  transition: opacity .3s;
  transform: translate(-50%, -50%);
  width: 280px;
}
.swipe-able-item {
  align-items: center;
  color: #fff;
  display: flex;
  flex-wrap: wrap;
  height: 100%;
  justify-content: center;
  margin: 0 auto;
  width: 100%;
}
.swipe-able-icon {
  display: block;
  margin: 40px auto 0;
  width: 80px;
}
.swipe-able-text {
  display: block;
  text-align: center;
  width: 100%;
}
@media screen and (max-width: 415px) {
  .is-animation {
    animation: my-animation 3.5s ease-in;
  }
  .is-animation-move-icon {
    animation: my-animation-move-icon 1s linear infinite;
  }
}
@keyframes my-animation-move-icon {
  0% {
    display: block;
    margin-left: 0%;
    scale: 1;
  }
  100% {
    display: block;
    opacity: 0;
    margin-left: 70%;
    scale: 1;
  }
}
@keyframes my-animation {
  0% {
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  50% {
    opacity: 1;
  }
  90% {
    opacity: .9;
  }
  100% {
    opacity: 0;
  }
}

↑細かい説明は省きますが、これで
「このTableはスワイプ可能です」という表示の部分が作成できます。

Grid.jsで作成したTableの上にスワイプ可能な表示を加える

こちらの画像のように、Tableの上にこの表示がつくと、「スワイプできるんだな」とわかりやすく伝えることができますね。(ちなみに、この時点でこの表示を確認してみたい場合、上のcss内の .swipe-able-container の opacity の値を 1 にすると確認することができます。完成形としては、次のセクションでご紹介する方法で、JavaScriptを使って表示させる形になります)

これを、次のセクションで
「Tableが画面内に入った時」「ふわっと表示させる」ことができれば
冒頭の動画でご紹介したものが作成できそうですね。

ではその方法について、次のセクションで書いていきます。

IntersectionObserver をつかって、上記のtableが「画面内に入った時」という状態を監視します

IntersectionObserver は、その名の通り
交差( Intersection ) を 観察 ( Observe ) することができる
Web API です。

これを JavaScript から呼び出して、
上のセクションで生成したテーブルが「いま見ている画面内に入った時」という状態を監視してみます。

IntersectionObserver に関する詳しい説明は、以前の記事を参照してください。

IntersectionObserver についてご紹介している記事:
[JavaScript]「スクロールして特定の位置をすぎたらふわっと表示」を簡単に実装する方法[IntersectionObserver]
[JavaScript]複数の要素を監視して、Viewportに入ったら表示させる方法[IntersectionObserver]

IntersectionObserver のコード

次のように書きます。

[JavaScript]

const myTarget = document.querySelector('.is-target');
const mySwipeAble = document.querySelector('.swipe-able-container');
const mySwipeAbleIcon = document.querySelector('.swipe-able-icon');

makeObserver();

function makeObserver() {
  let myObserver;
  
  const myOptions = {
    root: null,
    rootMargin: '0px 0px',
    threshold: '0'
  };
  
  myObserver = new IntersectionObserver(myIntersect, myOptions);
  myObserver.observe(myTarget);
}

function myIntersect(entries, myObserver) {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      mySwipeAble.classList.add('is-animation');
      mySwipeAbleIcon.classList.add('is-animation-move-icon');
    } else {
      mySwipeAble.classList.remove('is-animation');
      mySwipeAbleIcon.classList.remove('is-animation-move-icon');
    }
  });
}

1〜3行目は、html上の要素を取得して変数に格納する記述です。
5〜18行目は、IntersectionObserver を定義・呼び出している部分になります。
この部分の詳しい説明は、以前のこの記事を参照いただくと、詳しく書いてあります。ぜひ合わせて参照ください。
20行目〜末尾は、定義した IntersectionObserver が条件を満たしたら実行される
関数の部分です。ここで、上のセクションでご紹介した
cssアニメーションのclassを着脱することで、

「Tableが画面内に入った時」
「このTableはスワイプ可能です」という示唆を
「ふわっと表示させる」

ことができます。

完成形は次のようになります。

出現回数を1回にする

ここまでの記述で、上の動画でご紹介したような表示ができるようになります。

ただし、この状態だと
Tableが画面に入ってくるたびに、スワイプ可能を示す表示が
毎回出現します。

これを最初の1回だけにしたい場合は、
JavaScript部分の、次の部分の
else内を、次のように書き換えれば実現できます。

[JavaScript]

...(省略)...

function myIntersect(entries, myObserver) {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      mySwipeAble.classList.add('is-animation');
      mySwipeAbleIcon.classList.add('is-animation-move-icon');
    } else {
      return;
    }
  });
}

↑いちばん簡単な方法は、条件を満たすたびに着脱していたcssアニメーションのclassを、
外さずにそのままにする方法です。
これで、1回だけ表示する形に変えることが可能です。
※もちろん他にも、あらかじめJavaScript内で実行回数を定義しておく、それ用のフラグを持っておくなど、様々な方法が考えられます。

この記事のまとめ

今回は、これまでご紹介してきた

・IntersectionObserver
・Grid.js

この2つを使用して、
「対象のTableが画面内に入った時」
「このTableはスワイプ可能です」という示唆を
「ふわっと表示させる」

という方法について、記事を書きました。

なお、Tableの作成部分に Grid.js を使用していますが、
実は普通に作成したTableであっても、もちろん同じことが可能です。

また、IntersectionObserver を使用して
要素がViewportに入った時を検出する方法は、
覚えておくと今回の例以外の用途でも
幅広く応用が効き、きっとWeb制作の幅を広げてくれることと思います。

今年も年末。

今後も皆様のWeb制作が、もっと楽しいものとなるよう、
当サイトでは引き続きWeb制作に関する記事を執筆していきます。

※この記事は内容の品質向上を目的に、随時更新を行う場合があります。