先日のハッカソンでこういうのを作ってみました。自分用メモです。
Youtubeを再生させつつ、そのリストを右側に表示させます。
最終的にはこんな感じのリスト自動選択まで
ちなみにYoutubeプレイヤーはこちらをそのまま利用
BuefyのTable(b-table)を利用
今回create-nuxt-appでアプリ作成する際にCSSフレームワークでBuerfyを選択したのでこの枠組みのまま作ってみます。
b-table
というコンポーネントが用意されていて、これが結構便利だったので利用してみました。
シンプルな利用
シンプルな利用だとこんな感じ
<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側の説明が長くなりそうなのでカット。
<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
を追加します。
<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. セレクトされている要素の特定
Vue.jsだとthis.$el
で仮想DOMの要素アクセスができるっぽい?です。
(認識間違ってたらコメントください。)
b-tableで選択中のクラスは.b-table
と.is-selected
のクラスで検索できるのでこんな感じで検索できます。
this.$el.querySelector('.b-table .is-selected');
2. 特定した要素にスクロールさせる
scrollIntoView()
を使って実装できました。これは通常のJSのメソッドですが、あまり使ったことなかったので存在を初めて知りました。
まとめてみる
こんな感じです。今回僕の実装だと、再生後にセレクションをしているので、そのまま書くと絶妙なタイミングでis-selectedクラス
が付与されずうまくスクロールされなかったのでsetTimeout()
で若干タイミングをずらしています。
//スクロール
setTimeout(()=>{
const nowVideoElm = this.$el.querySelector('.b-table .is-selected');
nowVideoElm.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
},100);
behavior: 'smooth'
に設定するとアニメーションがいい感じですね。
まとめ
b-table
、scrollIntoView()
、this.$el
などを組み合わせて使ってみましたがけっこう便利だしユースケースあるかもしれないですね。
割とこのアニメーション好きです。