BLOG

ブログ

Nuxt3とVuetifyでドラッグスクロールを実装してみた

はじめに

こんにちは、遠藤です!

Nuxt3とVuetifyで開発している中で、ドラッグスクロールを導入したい!という要望を受け調べたのですが、なかなか参考記事に出会えませんでした。

実装方法はそこまで複雑ではないので、備忘録として残そうと思います!

最初にどどん!と結論と考え方を書いて、詳しい実装手順や例は後述します!

環境

今回はNuxt3とVuetify3を使用します。
ドラッグスクロールの実装には、vue-dragscrollというライブラリを使用します。

また、一部CSSを書く必要があるため、sassも入れておきます。 下記に実行環境をまとめます!!

Nuxt3.11.0
sass1.72.0
vue-dragscroll4.0.5
vuetify3.5.9

それでは参りましょう!

最初に結論

まずはキャプチャをご覧ください。
キャプチャのようにVuetifyで作成した要素をドラッグスクロール可能にするのが今回の目標です。

ざっくり説明すると、CSSでoverflow(はみ出てる要素の親要素)が発生しているタグに、”v-dragscroll”というライブラリ独自のディレクティブを指定します。

具体的な記述は以下の通りです。

<v-data-table v-dragscroll :items="sampleItems"></v-data-table>

実装方法

まずはライブラリをインストールします。
開発環境を起動するディレクトリで以下のコマンドを実行します。

npm install vue-dragscroll

package.jsonに”vue-dragscroll”: “^4.0.5”が追加されていれば成功です。

次にNuxtの実行環境でvue-dragscrollのライブラリをvueファイルのどこからでも使えるように設定します。pluginsディレクトリを作成しその中にdragscroll.tsを作成します。

中身の記述は以下の通りです。

import VueDragscroll from 'vue-dragscroll'

export default defineNuxtPlugin(({ vueApp }) => {
  vueApp.use(VueDragscroll)
})

設定自体は超簡単です。もしすでにある程度画面を作為した上で上記を実行している方は、 はみ出す子要素を持つタグにv-dragscrollディレクティブを追記することで、コンポーネントがドラッグスクロールできるようになっているはずです。

<div v-dragscroll> {はみ出す要素} </div>

まだ画面を作っていない方は、この後具体的な実装を一から説明しますのでよろしければ最後までお付き合いください。

と、その前に。

今回詰まったところ

今回はVuetifyコンポーネントをドラッグスクロールしたかったのですが、Vuetifyから提供されるタグにディレクティブを追記してもドラッグスクロールが反映されず苦戦しました。その時の状況と解決法を共有します。

私が今回ドラッグスクロールさせたかったのはv-data-tableコンポーネントです。

検証段階では、コンポーネントタグに”v-dragscroll”を追記しても、うまく反映されませんでした。書き方が間違っているわけではないので、何か他に原因があるはずです。

// うまくいかない
 <v-data-table v-dragscroll>something...</v-data-table>

v-data-tableのコンポーネントをブラウザの検証画面で見てみると、divが重なっているのがわかります。よく見ると一番上のdiv要素の中にwrapperのためのdiv要素がありますね。

v-data-tableのコンポーネントに”v-dragscroll”を適用する場合、一番外側のdiv要素から子要素がはみ出している必要があります。キャプチャで言うと一番上のdiv要素です。

しかしv-data-tableコンポーネントの中身では、v-table-wrpperというdiv要素にoverflow:autoが適用されており、一番外側のdiv要素ははみ出すコンポーネントを持たない状態になっていました。

overflowの設定はVuetify内部の仕様です。こちらからCSSにアクセスするには直接classを指定して、CSSを書き換える必要があります。

解決方法

今回の場合は下記のようなCSSを書くことで、v-table__wrpperというdiv要素のoverflow設定をunsetに設定しました。そして一番上のdiv要素にoverflowを設定することで、v-dragscrollディレクティブを設定した要素がはみ出す要素をもつことになり、ドラッグスクロールが実現します。

<style>
.v-table {
  overflow: hidden;
}
.v-table__wrapper {
  overflow: unset;
}
</style>

要点としては、「v-dragscrollがどの要素に適用されているか」「ディレクティブを追加した要素が、はみ出す子要素を持っているか」です。はみ出す子要素はVuetifyの仕様で自動的にoverflowが設定されている場合があるので、その場合はCSSを上書きします。

これが今回一番お伝えしたかった部分でした!!

では、実際の画面を一から作っていきましょう。 Nuxt3にあまり触れたことのない方のためにもなるべく細かく説明するので、 お急ぎの方はじゃんじゃん飛ばしながらお読みください。

実践

今回は大きく分けて以下の4つのステップで、Vuetifyコンポーネントを使用したドラッグスクロールを実装します。

  1. Nuxt3の環境構築とライブラリのインストール
  2. vue-dragcroll の設定
  3. Vuetifyの設定
  4. Vuetifyでドラッグスクロールを実装

Nuxt3の環境構築とライブラリのインストール

まずはNuxt3の環境を立ち上げます。

npx nuxi init sample1
cd sample1
npm install
npm run dev

これでlocalhost:3000にアクセスするとNuxt3の初期ページが表示されるはずです。

続いて、vue-dragscroll等、必要なライブラリ等をinstallします

// 一気にライブラリをイントールします
npm install vue-dragscroll sass vuetify 

正常にインストールすると、package.jsonの中身が以下のようになっているはずです

それでは次に各ライブラリを使用するための準備をします。

vue-dragscrollの設定

上記でもすでに紹介しましたが、vue-dragscrollを使用する準備をします。 ルートディレクトリにpluginsというディレクトリを新規作成します。

続いてその中にdragscroll.tsというファイルを作成しましょう。このTypescriptファイルの名称は任意ですのでわかりやすい名前に変更してOKです。

dragscroll.tsの中に以下の記述をします。 簡単なコードの意訳をすると「Vueファイル内全体で(VueDragscroll)を使えるようにするよ〜」といった感じです。

import VueDragscroll from 'vue-dragscroll'

export default defineNuxtPlugin(({ vueApp }) => {
  vueApp.use(VueDragscroll)
})

これでpligins/dragscrollをnuxt全体に反映させることができました。

では早速ドラッグスクロールができるか試してみましょう。

app.vueの内容を以下のものに書き換えます。 sassをインストールしているので、<style>内でscssの記法が使えます。

overflowがはみ出す要素、dragscrollがはみ出される要素ですので、外側のdiv要素にv-dragscrollのディレクティブをつけます。

<template>
  <div class="dragscroll" v-dragscroll>
    <div class="overflow"></div>
  </div>
</template>
<style scoped>
.dragscroll {
  width: 300px;
  height: 300px;
  border: 1px solid #000;
  overflow: scroll;
}
.overflow {
  width: 500px;
  height: 500px;
  background: #ccc;
  border: 5px solid #000;
}
</style>

それでは開発環境を立ち上げて実際にドラッグスクロールができるか確認します。

無事ドラッグスクロールできてますね。

それでは次はVuetifyでドラッグスクロールを実装してみます。

Vuetifyの設定

まずはVuetifyをNuxt全体で使用できるように設定します。 pluginsにvuetify.tsを作成し下記のように記述します。

簡単に意訳すると、「Nuxtの中でVuetifyコンポーネントを使えるようにするよ〜」と言った具合いです。

import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components'

export default defineNuxtPlugin( nuxtApp => {
    const vuetify = createVuetify({
        components
    });

    nuxtApp.vueApp.use( vuetify );
});

この設定だけではVuetifyは動きません。nuxt.config.tsを開き以下のように下記変えます。

// <https://nuxt.com/docs/api/configuration/nuxt-config>
export default defineNuxtConfig({
  devtools: { enabled: true },
  css: [
    "vuetify/lib/styles/main.sass"
],
build: {
  transpile: ["vuetify"]
},
})

上記を簡単に意訳すると「CSSはVuetifyライブラリのものを使って、ビルドするときもVuetifyのコードをいい感じのJavaScriptにしますよ」という具合いです。厳密には違うのかもしれませんが、ここでは深掘りしません。

実際にVuetifyのコンポーネントを使用できるか確認します。

app.vueに下記のように追記します。

<template>
  <div class="dragscroll" v-dragscroll>
    <div class="overflow"></div>
  </div>
  <v-btn>button</v-btn>  ← 追記
</template>
<style scoped>
.dragscroll {
  width: 300px;
  height: 300px;
  border: 1px solid #000;
  overflow: scroll;
}
.overflow {
  width: 500px;
  height: 500px;
  background: #ccc;
  border: 5px solid #000;
}
</style>

添付のようなボタンが出てきていれば、Vuetifyコンポーネントを使用できています。

それでは今回の肝、データテーブルのドラッグスクロールを作成してみましょう。

Vuetifyでドラッグスクロールを実装

下記にコードを用意しましたので、app.vueの内容をまるっと書き換えてみてください。

<script setup>
// データの中身
const sampleItems = [...Array(10)].map((_, i) => {
  return {
    sample_a: "a".repeat(50),
    sample_b: "b".repeat(50),
    sample_c: "c".repeat(50),
  };
});
</script>
<template>
  <div class="width">
    <v-data-table v-dragscroll :items="sampleItems"><template #bottom /></v-data-table>
  </div>
</template>
<style>
.width {
  width: 800px;
  border: 1px solid #000;
}
</style>

簡単に説明すると、scriptタグ内ではテーブルに表示するサンプルのデータを定義しています。

templateタグ内でv-data-tableコンポーネントを呼び出し、scriptで定義したサンプルデータをコンポーネントに渡すことで、テーブルにサンプルのデータが描画される仕組みです。

以下のように表示されていれば成功です。データテーブルにスクロールが発生していると思います。

それではドラッグスクロールをこのテーブルに適用します。

まずはoverflowがどこに設定されているか、ブラウザの検証ツールを使用して確認してみます。

v-table-wrapperというクラスに、overflowが設定されています。

ではこのclassを上書きしましょう。先ほどのapp.vueに以下のstyleを追記します。

<style>
.width {
  width: 800px;
  border: 1px solid #000;
}
// 追記
.v-table__wrapper {
  overflow: unset;
}
</style>

v-table__wrapperで自動的に設定されたoverflowを相殺すると、以下のような画面になります。

はみ出した要素を隠すために、v-data-tableコンポーネントの親タグ(class=’v-table’)に新たにoverflowを追記します。

<style>
.width {
  width: 800px;
  border: 1px solid #000;
}

// 追記
.v-table {
  overflow: hidden;
}
//
.v-table__wrapper {
  overflow: unset;
}
</style>

これでデータテーブルがドラッグスクロールできるようになるはずです!
一番最初にご覧いただいたキャプチャのようにドラッグスクロールができていれば今回の目標は達成となります。いかがでしょうか??

※上記は2024年3月現在の仕様であり、今後ライブラリのバージョンが更新されることで、解消されるかもしれません。あらかじめご了承ください。

さいごに

以上がNuxt3とVuetifyでドラッグスクロールを実装してみた例でした!

ライブラリの更新頻度が多いとは言えないのですが、しっかりNuxt3に対応していたりします。 Mac bookだとトラックパッドがあるのでスクロールが煩わしくなることはないのですが、 Windowsユーザーはマウス操作が多いのでドラッグスクロールは意外と需要がありそうです…!

ライブラリを併用する例はあまり文献がなかったので、実際に動かしてみて勉強になることが多かったです!

そのうちVuetifyが進化すれば、ドラッグスクロール用の設定等も登場するかもしれませんね!

以上、遠藤でした!
それでは、またの機会に〜!