LoginSignup
4
1

More than 3 years have passed since last update.

Nuxt.jsとBuefyでYoutubeプレイヤーを作るメモ

Last updated at Posted at 2020-08-15

先日のハッカソンでこういうのを作ってみました。自分用メモです。

https://djuko.cf

Youtubeを再生させつつ、そのリストを右側に表示させます。

最終的にはこんな感じのリスト自動選択まで

ちなみにYoutubeプレイヤーはこちらをそのまま利用

参考: Nuxt.js 2でYoutubeプレイヤー埋め込み

BuefyのTable(b-table)を利用

今回create-nuxt-appでアプリ作成する際にCSSフレームワークでBuerfyを選択したのでこの枠組みのまま作ってみます。

https://buefy.org/documentation/table#selection

b-tableというコンポーネントが用意されていて、これが結構便利だったので利用してみました。

シンプルな利用

シンプルな利用だとこんな感じ

Player.vue

<template>
//省略

<b-table
  :data="data"
  :columns="columns"
  ></b-table>

//省略
</template>

<script>
//省略
  data(){
    return{
      //省略

      data: <再生リスト>,
      columns: [
        {
            field: 'rank',
            label: 'DAM RANK/DAY',
            numeric: true,
        },
        {
            field: 'title',
            label: 'TITLE',
        },
      ],
    }
  }
//省略
</script>

キレイに表示されますね。

ただ、これだけだとただの表なので現在何が再生されているかの選択がされていないため、プレイヤー的には物足りないです。

セレクションを有効にする

selected.syncというプロパティを有効にしてみます。

どこが再生されているか分かるようになりました。

this.selectedに再生中の音楽データを入れ込むようにしてあげると、b-tabel側で選択状態になります。ここのロジック部分はYoutube Player API側の説明が長くなりそうなのでカット。

Player.vue

<template>

//省略
<b-table
  :data="data"
  :columns="columns"
  :selected.sync="selected"
  ></b-table>

//省略

</template>

<script>
//省略
  data(){
    return{
      //省略

      data: <再生リスト>,
      columns: [
        {
            field: 'rank',
            label: 'DAM RANK/DAY',
            numeric: true,
        },
        {
            field: 'title',
            label: 'TITLE',
        },
      ],
      selected: {}, //再生中の音楽データ
    }
  }
//省略
</script>

テーブルのスクロールに対応する(stickyHeaders)

このままだとこんな感じで再生リストが長くなった際にページがものすごく長くなってしまって操作が大変になります。

これを

こうします

sticky-headerのプロパティを有効にします。
<template>側では:sticky-header="stickyHeaders"を追加、<script>側ではdataにstickyHeaders: trueを追加します。

Player.vue

<template>

//省略
<b-table
  :data="data"
  :columns="columns"
  :selected.sync="selected"
  :sticky-header="stickyHeaders"
  ></b-table>

//省略

</template>

<script>
//省略
  data(){
    return{
      //省略

      data: <再生リスト>,
      columns: [
        {
            field: 'rank',
            label: 'DAM RANK/DAY',
            numeric: true,
        },
        {
            field: 'title',
            label: 'TITLE',
        },
      ],
      selected: {}, //再生中の音楽データ
      stickyHeaders: true //スクロール対応
    }
  }
//省略
</script>

自動的にスクロールさせる

ここからはb-tableの話というよりはVue.jsやJavaScriptの話

現状だと、スクロール対応は出来てるのですが、出来ればページを開いたときに自動的にその要素を表示させたいですよね。

こんな感じ

ここが結構情報がなくて大変でした。

  • 1. セレクトされている要素の特定
  • 2. 特定した要素にスクロールさせる

結果この二つのステップで実装できました。

1. セレクトされている要素の特定

Vue.jsだとthis.$elで仮想DOMの要素アクセスができるっぽい?です。
(認識間違ってたらコメントください。)

参考: DOM要素に対応するvue.jsコンポーネントを見つけるには

b-tableで選択中のクラスは.b-table.is-selectedのクラスで検索できるのでこんな感じで検索できます。

this.$el.querySelector('.b-table .is-selected');

2. 特定した要素にスクロールさせる

scrollIntoView()を使って実装できました。これは通常のJSのメソッドですが、あまり使ったことなかったので存在を初めて知りました。

参考: あまり知られてなさそうなメソッド element.scrollIntoView()

まとめてみる

こんな感じです。今回僕の実装だと、再生後にセレクションをしているので、そのまま書くと絶妙なタイミングでis-selectedクラスが付与されずうまくスクロールされなかったのでsetTimeout()で若干タイミングをずらしています。

  //スクロール
  setTimeout(()=>{
    const nowVideoElm = this.$el.querySelector('.b-table .is-selected');
    nowVideoElm.scrollIntoView({
      behavior: 'smooth',
      block: 'center',
    });
  },100);

behavior: 'smooth'に設定するとアニメーションがいい感じですね。

まとめ

b-tablescrollIntoView()this.$elなどを組み合わせて使ってみましたがけっこう便利だしユースケースあるかもしれないですね。

割とこのアニメーション好きです。

https://djuko.cf

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1