【Vue】Vuetify + TypeScript で トップに戻る 丸ボタンを作る

■ はじめに

https://dk521123.hatenablog.com/entry/2020/12/26/000242
https://dk521123.hatenablog.com/entry/2021/02/14/180324
https://dk521123.hatenablog.com/entry/2021/02/21/162236

の続き。

今回は、Vuetify で「トップに戻る 」の丸ボタンを作ってみる。
ついでに、汎用化できるように、コンポーネント化してみた。

【1】使用しているTips

別に必須ではないが、以下の機能を使う。

1)アイコン - v-icon
2)アニメーション - Transitions
3)ツールチップ - v-tooltip

1)アイコン - v-icon

* アイコン表示
 => 今回は、Material Design Icons を選んだ場合
* 「mdi-【アイコン】」で使用する

https://vuetifyjs.com/ja/components/icons/

2)アニメーション - Transitions

* アニメーション効果を使う

https://vuetifyjs.com/ja/styles/transitions/

3)ツールチップ - v-tooltip

* ツールチップ表示
 + open-delay : 表示までの時間差[ms]

https://v2.vuetifyjs.com/ja/components/tooltips/
https://vuetifyjs.com/ja/api/v-tooltip/

【2】サンプル

例1:vueファイルに直接書いた場合

/views/Home.vue

<template>
  <v-container class="scroll-y">
    <v-layout
      align-center
      justify-center
    >
      <v-flex xs12>
        <v-toolbar color="cyan" dark id="scroll-target">
          <v-toolbar-side-icon></v-toolbar-side-icon>
          <v-toolbar-title>Scroll Down</v-toolbar-title>
        </v-toolbar>
        <!-- ここから -->
        <v-tooltip left open-delay="900">
          <template v-slot:activator="{ on }">
            <v-fab-transition>
              <v-btn
                v-scroll="onScroll"
                v-show="isShowGoToTopButton"
                v-on="on"
                fab
                dark
                fixed
                bottom
                right
                color="secondary"
                @click="onClickGoToTopButton"
              >
                <v-icon dark large>
                  mdi-chevron-up
                </v-icon>
              </v-btn>
            </v-fab-transition>
          </template>
          <span>Scroll to top</span>
        </v-tooltip>
        <!-- ここまで -->
        <v-card style="height: 1000px">
          <v-card-title primary-title>
            <div>
              This example demonstrates
              how to create a "scroll to top"
              button that becomes visible
              when the user starts to scroll the page.
            </div>
          </v-card-title>
        </v-card>
      </v-flex>
    </v-layout>
  </v-container>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component({
  components: {
  },
})
export default class Home extends Vue {
  private isShowGoToTopButton = false;

  onScroll(event: Event) {
    if (typeof window === 'undefined') {
      return;
    }
    let scrollTop = 0;
    if (event.target instanceof HTMLInputElement) {
      scrollTop = event.target.scrollTop;
    }
    const top = window.pageYOffset || scrollTop || 0;
    this.isShowGoToTopButton = top > 20;
  }

  onClickGoToTopButton() {
    this.$vuetify.goTo(0);
  }
}
</script>

例2:コンポーネント化した場合

/components/GoToTopButton.vue

<template>
  <v-tooltip left open-delay="900">
    <template v-slot:activator="{ on }">
      <v-fab-transition>
        <v-btn
          v-scroll="onScroll"
          v-show="isShowGoToTopButton"
          v-on="on"
          fab
          dark
          fixed
          bottom
          right
          color="secondary"
          @click="onClickGoToTopButton"
        >
          <v-icon dark large>
            mdi-chevron-up
          </v-icon>
        </v-btn>
      </v-fab-transition>
    </template>
    <span>Scroll to top</span>
  </v-tooltip>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class GoToTopButton extends Vue {
  private isShowGoToTopButton = false;

  onScroll(event: Event) {
    if (typeof window === 'undefined') {
      return;
    }
    let scrollTop = 0;
    if (event.target instanceof HTMLInputElement) {
      scrollTop = event.target.scrollTop;
    }
    const top = window.pageYOffset || scrollTop || 0;
    this.isShowGoToTopButton = top > 20;
  }

  onClickGoToTopButton() {
    this.$vuetify.goTo(0);
  }
}
</script>

/views/Home.vue

<template>
    <!-- 略 -->
        <!-- ここから -->
        <GoToTopButton />
        <!-- ここまで -->
    <!-- 略 -->
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import GoToTopButton from '../components/GoToTopButton.vue';

@Component({
  components: {
    GoToTopButton,
  },
})
export default class Home extends Vue {
}
</script>

参考文献

https://qiita.com/hiroyukiwk/items/fcb76893457daf1a6327
https://codepen.io/carlos-henreis/pen/vzXKBJ

関連記事

Vue.js ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/04/30/000000
Vue.js ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/12/19/000000
Vuetify ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/12/26/000242
Vuetify ~ コンポーネント編 ~
https://dk521123.hatenablog.com/entry/2021/02/14/180324
Vuetify ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2021/02/21/162236
Vuetify に関するトラブルシューティング
https://dk521123.hatenablog.com/entry/2021/02/08/000000