LoginSignup
3
2

More than 3 years have passed since last update.

【Nuxt.js】スクロールアニメーション実践編:思わず最後までスクロール

Last updated at Posted at 2020-01-30

picture_pc_ed98807d7df90b1f046ef8e3e3a0d1c4.gif

前置き

スクロールエフェクトのアニメーション
青い背景が左からニョキっと出てきます👀
動きがあるとスクロールしたくなりますよね🎵

今回はシンプルですが、
背景やタイトルを動かしたり
アイテムを浮き出させたり、使い方は様々です🌟

構成

大まかにこんな感じです🍒
・mouted()でDOMから
 Y座標を取ってきてdata更新
・Y座標を1増やし(下げる)watchを反応させる
 対応するsection idにanimationクラスを付与

完成コード

今回はいつものようにStep順ではなく
構成で全体感を説明しているため、
部分的に分けて解説していきます!

・section id="second"
 スクロールしていき
 この領域に入ったらアニメーション開始💃✨

index.vue
<template>
 <div class="page">
   <p>スクロールしてみよう</p>
   <section id="first">
     <p>もう少し</p>
   </section>
   <section id="second">
     <div class="bg">
       <p>ここが動く</p>
       <div />
     </div>
   </section>
   <section id="third">
     <p>伸びたね</p>
   </section>
 </div>
</template>

<script>
import Vue from 'vue'

export default {
 data () {
   return {
     positionY: 0,
     positions: {
       second: 0,
     },
   }
 },
 watch: {
   positionY(to, from) {
     const scrollOffset = to + 100
     let el

     if (this.positions.second <= scrollOffset) {
       el = document.getElementById('second')
       el.setAttribute('class', 'animation')
     }
   },
 },
 mounted() {
   window.addEventListener('scroll', this.checkScroll)

   this.positions = {
     second: document.getElementById('second').getBoundingClientRect().top,
   }

   this.positionY++
 },
 methods: {
   checkScroll() {
     this.positionY = window.scrollY ? window.scrollY : window.pageYOffset
   },
 }
}
</script>

<style lang="scss" scoped>
 #second {
 > .bg {
   width: 100%;
   height: 100%;

   div {
     width: 25%;
     height: 200px;
     background: linear-gradient(269.76deg, #1F3345 0%, #333A56 100.52%);
     transition: all 3s cubic-bezier(0.215, 0.61, 0.355, 1);
     display: block;
   }
 }
 &.animation {
   > .bg {
     div {
       width: 100% !important;
       display: block;
     }
   }
 }
}
</style>

template

section idで区切ります。
watchでスクロールによる
idへのクラスを付与するためです。

data

・positionY
 Y軸を取得しwatchを反応させるため
・positions
 該当idの一番上の位置を代入させるため

index.vue
<script>
import Vue from 'vue'

export default {
 data () {
   return {
     positionY: 0,
     positions: {
       second: 0,
     },
   }
 },
}
</script>

mounted()

解説はインラインのコメントにて。
基本的にスクロールや座標の指定は
DOMの表示位置から取るため
大体のことはここに書きます✍️

index.vue
<script>
import Vue from 'vue'

export default {
 mounted() {
   // スクロールイベントを追加
   window.addEventListener('scroll', this.checkScroll)

   this.positions = {
     // section id="second"のtopのY座標をdataのsecondに代入
     second: document.getElementById('second').getBoundingClientRect().top,
   }

   // watchを反応させるために1だけ下げる
   this.positionY++
 },
}
</script>

methods

解説はインラインのコメントにて。
先ほどのmountedで実行している関数です。
ページ内容に関係なく今いる位置の一番上の
Y軸の位置を取れば良いだけなのでDOM関係なし!

index.vue
<script>
import Vue from 'vue'

export default {
  methods: {
   checkScroll() {
     // window.scrollYでY軸取得できる
     // this.positionY = window.scrollYのみでもOK
   // IE対応のために三項演算 式1? 式2: 式3
     this.positionY = window.scrollY ? window.scrollY : window.pageYOffset
   },
  }
}
</script>

watch

解説はインラインのコメントにて。

index.vue
<script>
import Vue from 'vue'

export default {
  watch: {
   // dataのpositionY
   // fromが変化する前の値, toが変化後の値
   positionY(to, from) {
     // sectionがy=0の1番上に来た時点ではなく、
   // + 100の位置に来た時点で反応させたい
     const scrollOffset = to + 100
     let el

     // secondのtopの位置が50、それ以下(上)になったら
     if (this.positions.second <= scrollOffset) {
       // id="second"に
       el = document.getElementById('second')
       // animationというクラスを追加
       el.setAttribute('class', 'animation')
     }
   },
 },
}
</script>

スクロールにより
途中でanimationクラスが
追加されているのが分かりますね👀

css

それぞれを書けばOK!
・通常時
・animationクラス付与時

変化が分かりやすいように
transitionは3秒と長めにとりました。

index.vue
<style lang="scss" scoped>
 #second {
 > .bg {
   width: 100%;
   height: 100%;

   div {
     width: 25%;
     height: 200px;
     background: linear-gradient(269.76deg, #1F3345 0%, #333A56 100.52%);
     transition: all 3s cubic-bezier(0.215, 0.61, 0.355, 1);
   }
 }
 &.animation {
   > .bg {
     div {
       width: 100% !important;
     }
   }
 }
}
</style>

🌟記事の量が増えてきました。
 知りたい内容があれば、
 aLizとそのキーワードでググってみてください♪

 ヒットしない場合、
 こんな記事が欲しい!とコメントいただければ
 記事にするかもしれません🎈

記事が公開したときにわかる様に、
note・Twitterフォローをお願いします😀

3
2
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
3
2