ウェルカムページは、全4回に渡って構築します。
1/4 ウェルカムページを構築するコンポーネントファイルの作成
3/4 スクロールイベントでツールバーの色を変える(今ここ)
前回までのおさらい
前回はアイキャッチ画像を設置し、ツールバーにメニューボタンを用意しました。
今回達成すること
ツールバーのスタイリングとメニューボタンの実装を行います。
ツールバーのスタイリング
ツールバーカラーは、スクロールを検知するイベントを設定し、
- アイキャッチ上に表示されるときは透明で、
- スクロールでアイキャッチを通過する場合は白色に
変化させます。
メニューボタンの実装
メニューボタンにはVuetifyのgoTo()
メソッドを使用し、指定した場所までスクロールさせます。
それでは実装に入りましょう。
スクロールを検知してツールバーの色を変える
下記の手順に沿って実装を行います。
welcome.vue からアイキャッチ画像の高さを送り、- スクロールを検知するイベントリスナーを追加。
- アプリ共通のツールバーの高さをVuexに保有する。
- スクロールポイントで色が切り替わる算出プロパティを追加する。
1. welcome.vueからアイキャッチの高さを送るんじゃ
imgHeight: 500
を、
front/layouts/welcome.vue
<template>
<v-app>
<!-- img-heightを追加 -->
<wel-app-bar
:menus="menus"
:img-height="imgHeight"
/>
...
props
で受け取ります。
front/components/welcome/welAppBar.vue
<script>
export default {
props: {
menus: {
type: Array,
default: () => []
},
// 追加
imgHeight: {
type: Number,
default: 0
}
},
...
}
</script>
2. addEventListenerを追加するんじゃ
addEventListener
を追加します。
front/components/welcome/welAppBar.vue
...
</v-btn>
</v-toolbar-items>
<!-- 確認のため追加 -->
{{ scrollY }}
</v-app-bar>
</template
<script>
export default {
...
data ({ $config: { appName } }) {
return {
appName,
// 追加
scrollY: 0
}
},
// 追加
mounted () {
window.addEventListener('scroll', this.onScroll)
},
beforeDestroy () {
window.removeEventListener('scroll', this.onScroll)
},
methods: {
onScroll () {
this.scrollY = window.scrollY
}
}
// ここまで
}
</script>
-
mounted ()
... Vueインスタンスがマウントされた後に実行される。Vue内のデータや命令がHTML要素に紐付けされた後、つまりVueの実行準備が完全に整った後に実行されます。
-
addEventListener
... スクロールを検知するとthis.onScroll
メソッドが呼ばれる。これはJavaScriptのメソッドで、第一引数に指定したイベントが発生した時に第二引数の関数を実行します。
-
beforeDestroy ()
... Vueインスタンスが破壊される前に実行される。ページ遷移などにより、Vue内のデータや命令が削除される直前に実行されます。
-
removeEventListener
...addEventListener
で追加したイベントを削除する。addEventListener
によるメモリ消費を避けるために、追加したイベントは不要になるタイミングで削除しましょう。 -
onScroll ()
...データで用意したscrollY
にウィンドウのスクロール値を代入する。 -
window
... JavaScriptに用意されているオブジェクト。ブラウザ側だけで実行されるオブジェクトです。
Nuxt.jsが
Universal
モードの場合、サーバー側のレンダリング時にエラーになるため対応が必要です。
windowオブジェクトをクライアントサイドだけで実行する方法
export default {
data () {
return {
isClient: process.client
}
},
mounted () {
if (this.isClient) {
window.addEventListener('scroll', this.onScroll)
}
}
...
}
ブラウザでスクロール検知を確認してみましょう。
ツールバー右の数字がスクロールによって変化していれば成功です。
確認が取れたらHTMLは削除します。
front/components/welcome/welAppBar.vue
....
</v-btn>
</v-toolbar-items>
<!-- {{ scrollY }} 削除 -->
</v-app-bar>
</template>
3. ツールバーの高さをVuexに保有するんじゃ
ツールバーの高さは、
- ウェルカムページで使用するツールバーと、
- ログイン・会員登録ページで使用するツールバー(まだ未作成)
同じ高さとなります。
そこで双方のコンポーネントから参照できるように、Vuexの
front/store/index.js
export const state = () => ({
loggedIn: false,
// 追加
styles: {
beforeLogin: {
appBarHeight: 56
}
}
})
...
4. 色を切り替える算出プロパティを追加するんじゃ
アイキャッチ画像の高さを基準に色を切り替える算出プロパティを作成します。
算出プロパティとは、computed
内に宣言する関数のことです。
色を切り替えるタイミングは、「スクロール値がアイキャッチ画像からツールバーを引いた高さ」以上の場合に白、そうでなければ透明とします。
計算式で表すと、「スクロール値 > (500px - 56px) = 白」となります。
スクロールポイントでtrueを返す算出プロパティを追加する
true
を返す算出プロパティを追加します。
スクロールポイントは「アイキャッチ画像の高さ(500px) - ツールバーの高さ(56px) = 444px」となります。
front/components/welcome/welAppBar.vue
export default {
...
// $storeを追加
data ({ $config: { appName }, $store }) {
return {
appName,
scrollY: 0,
// 追加
appBarHeight: $store.state.styles.beforeLogin.appBarHeight
}
},
// computed追加
computed: {
isScrollPoint () {
return this.scrollY > (this.imgHeight - this.appBarHeight)
}
},
mounted () {
...
}
isScrollPoint
は、デフォルトでfalse
スクロールポイントを経過するとtrue
となります。
色を切り替える算出プロパティを追加する
isScrollPoint
を基準に色を切り替える算出プロパティを追加し、<v-app-bar>
に新たなバインドキーを追加します。
front/components/welcome/welAppBar.vue
<template>
<!-- 新たなバインドキーを追加 -->
<v-app-bar
app
:dark="!isScrollPoint"
:height="appBarHeight"
:color="toolbarStyle.color"
:elevation="toolbarStyle.elevation"
>
...
</v-app-bar>
</template>
<script>
export default {
...
computed: {
...
// 追加
toolbarStyle () {
const color = this.isScrollPoint ? 'white' : 'transparent'
const elevation = this.isScrollPoint ? 4 : 0
return { color, elevation }
}
},
mounted () {
...
</script>
-
v-app-bar
のバインドキー-
dark
... ダークモードにする。スクロールポイントによってツールバー上の文字色を白か黒に切り替えています。
-
height
... ツールバーの高さ指定。 -
color
... ツールバーの色を指定。 -
elevation(エレベーション)
... ツールバーの影の濃さ。0(影無し) ~ 24の値を指定可能。スクロールポイントによって0か4に切り替えています。
-
編集が終わったらブラウザで確認してみましょう。
ツールバーの色と影、文字色が変化します。
メニューボタンにスクロールメソッドを追加する
メニューボタンの実装に入ります。
クリックイベントを追加する
クリックすると下記の場所へスクロールするイベントを追加します。
- 各メニューボタンは、指定の場所へ
- アプリのロゴをクリックしたらページトップへ
goTo()
メソッドを追加し、HTMLには@click
イベントを追加します。
front/components/welcome/welAppBar.vue
<template>
<v-app-bar
app
:dark="!isScrollPoint"
:height="appBarHeight"
:color="toolbarStyle.color"
:elevation="toolbarStyle.elevation"
>
<!-- @click.native 追加 -->
<app-logo
@click.native="goTo('scroll-top')"
/>
...
<v-toolbar-items class="ml-2">
<!-- @click 追加 -->
<v-btn
v-for="(menu, i) in menus"
:key="`menu-btn-${i}`"
text
@click="goTo(menu.title)"
>
{{ $t(`menus.${menu.title}`) }}
</v-btn>
</v-toolbar-items>
</v-app-bar>
</template>
<script>
export default {
...
methods: {
...
// 追加
goTo (id) {
this.$vuetify.goTo(`#${id}`)
}
}
}
</script>
-
@click.native(ネィティブ)
... 子コンポーネントへクリックイベントを追加する場合は、native
拡張子が必要。 -
this.$vuetify.goTo('ID')
... 引数に指定したID要素までスクロールするVuetifyのメソッド。
スクロールポイントにIDを追加する
まだID要素を用意していないので、今のままクリックしてもエラーになります。
各メニューコンテンツを置いているv-img
とv-col
にIDを追加します。
front/layouts/welcome.vue
<template>
...
<!-- id="scroll-top" 追加 -->
<v-img
id="scroll-top"
dark
src="https://picsum.photos/id/20/1920/1080?blur=5"
gradient="to top right, rgba(19,84,122,.6), rgba(128,208,199,.9)"
:height="imgHeight"
>
...
<v-row
v-for="(menu, i) in menus"
:key="`menu-${i}`"
>
<!-- :id="menu.title" 追加 -->
<v-col
:id="menu.title"
cols="12"
>
<v-card flat>
...
(まだの方は)コンテナを起動してブラウザで確認してみましょう。
root $ docker-compose up
ボタンをクリックして所定の位置までスクロールすれば実装完了です。
コミットしとく
今回の作業はここまで。
ここまでの変更をコミットしておきましょう。
root $ cd front
front $ git commit -am "toolbar_add_scroll_event"
frong $ cd ..
root $ # 戻っておく
まとめ
今回は、ツールバーにスクロールを検知するイベントを追加し、メニューボタンへクリックイベントを追加しました。
今回作成したスクロールを検知するイベントはVue.js単体でも実装可能です。
「トップに戻る」ボタンも今回のテクニックが使用されています。
ぜひ今回の実装を参考に挑戦してみてください:cowboy_hat_face:
さて、次回は
次回はツールバーにログイン画面と会員登録画面に遷移するリンクボタンを設置し、フッターなどのレイアウトを完成させます。
次回でウェルカムページは完成でーす!(あと少し↓)