jQueryのあの動きをVue.jsでやってみた

モダンな開発を導入して脱jQueryの観点で普段何気なく使っているjQueryをプレーンなJavaScriptないしフレームワークに沿った書き方に置き換える必要性が出てきます。例えば、Vue.jsで要素の動きを再現しようとすると、案の定盲点が多く、「あれ?これjQueryコピペで作れちゃうけどVueだとどうやって書けば良いの?」という事案が自分の中で多発しています。
最近特にサイトの動きやエフェクトについて改めて整理したいと思い、学習メモとして残すためにも、こちらのシリーズを書くことにしました!同じ勉強をしている人の役に立てればと思います。
最初の一回目は、要素が「ランダムにふわっとfadeUp」する動きをVueで再現するコードとその気付きを書きたいと思います。

この記事の目次

まずは完成した全体像をこちらからご覧ください。
https://codepen.io/sue0606777/pen/vYdVRrG
*CodePenに遷移します

前提:この記事はVue.jsをある程度習得した方向けです。Vue.jsの基礎について解説しません。

【ランダムにふわっとfadeUp編 その①】

サイトを見る時よくあるふわっとフェードアップして現れる要素の動きをVue+GSAPで再現します。ただここのこだわりポイントは、一斉にフェードアップでも、順番にフェードアップでもなく、ランダムに!!です。

random_fadeUp.html

      
      <div id="app">
        <p>ページに遷移すると、ランダムに現れる</p>

        <!--読み込みしてふわっと-->
        <transition-group appear
          tag="ul"
          class="randomBox"
          @before-enter="beforeEnter"
          @enter="enter"
          @leave="leave"
          :css="false"
        >
          <li class="box" v-for="(moveData,index) in moveDatas" :key="moveData" :data-index="randomsA[index]">{{ moveData }}</li>
        </transition-group>

      </div>

      
    

まずは要素のlistを<li>で用意し、トランジションを付与する<transition-group>で包みます。appear属性を入れることで、要素が読み込まれた瞬間一回だけtransitionが発動するというわけです。

一旦jsのほうを見てみましょう。

random_fadeUp.js

      
      const app = new Vue({
        el: '#app',
        data: {
            moveDatas: ['a','b','c','d','e'],
            randomsA: [],
        },
        created(){
            this.randomCreat(this.moveDatas,this.randomsA)
        },
        mounted(){

        },
        methods: {
          randomCreat(n,m){
            /** 最小値と最大値 */
            let min = 0, max = n.length;
            
            /** 重複チェックしながら乱数作成 */
            for(i = min; i <= max; i++){
              while(true){
                var tmp = this.intRandom(min, max);
                if(!m.includes(tmp)){
                  m.push(tmp);
                  break;
                }
              }
            }
          },

          /** min以上max以下の整数値の乱数を返す */
          intRandom(min, max){
            return Math.floor( Math.random() * (max - min + 1)) + min;
          },

          ///アニメ挙動//
          beforeEnter(el) {
            el.style.opacity = 0
            el.style.transform = 'translateY(100px)'
          },
          enter(el, done) {
            gsap.to(el, {
              opacity: 1,
              y: 0,
              delay: el.dataset.index * 0.15,
              onComplete: done
            })
          },
          leave(el, done) {
            gsap.to(el, {
              opacity: 0,
              y: 100,
              delay: el.dataset.index * 0.15,
              onComplete: done
            })
          }
        }
      })
      
    

ここのポイントは:

  • <li>のdata-index属性にランダムの値を入れ、それぞれのdata-index属性値によって、delay: el.dataset.index * 0.15の結果がランダムになり、アニメーションが発動するタイミングもランダムになります。
  • 関数randomCreatはmountedの中ではなく、createdの中に入れないと、ライフサイクル上、要素がhtmlとして作られる前にdata-index属性に入れる値を作ることができないため、うまく動きません。

以上、「ランダムにふわっとfadeUp」を作ることができました。

【ランダムにふわっとfadeUp編 その②】

次は応用編で、スクロールしたらふわっとフェードアップして現れる要素の動きもVue+GSAPで再現します。

random_fadeUp.html

      
      <!--スクロールしてふわっと-->
      <transition-group
        tag="ul"
        class="randomScroll"
        id="randomScroll"
        @before-enter="beforeEnter"
        @enter="enter"
        @leave="leave"
        :css="false"
      >
        <li class="box" v-for="(scrollData,index) in scrollDatas" :key="scrollData" :data-index="randomsB[index]" v-show="isScroll">{{ scrollData }}</li>
      </transition-group>
      
    

こちらも①とほぼ変わらず、まずは要素のlistを<li>で用意し、トランジションを付与する<transition-group>で包みます。ここではappear属性を入れません。id="randomScroll"と<li>v-show="isScroll"も追加します。

jsのほうは①をベースに必要なdata(scrollDatas、randoms2、isScroll)と関数(handleScroll)、イベントリスナー(window.addEventListener)を追加します。

random_fadeUp.js

      
      const app = new Vue({
        el: '#app',
        data: {
            moveDatas: ['a','b','c','d','e'],
            scrollDatas: ['a','b','c','d','e','f','g'],
            randomsA: [],
            randomsB: [],
            isScroll: false
        },
        created(){
            this.randomCreat(this.moveDatas,this.randomsA)
            this.randomCreat(this.scrollDatas,this.randomsB)
        },
        mounted(){
          let that = this
          window.addEventListener('scroll', function(){that.handleScroll('randomScroll')})
        },
        destroyed() {
          window.removeEventListener('scroll', function(){that.handleScroll('randomScroll')})
        },
        methods: {
          handleScroll(n) {
            const t = document.getElementById(n)
            const d = t.offsetTop - window.pageYOffset + 100
            if (d < window.innerHeight ) {
              this.isScroll = true
            } else {
              this.isScroll = false
            }
          },

          randomCreat(n,m){
            /** 最小値と最大値 */
            let min = 0, max = n.length;
            
            /** 重複チェックしながら乱数作成 */
            for(i = min; i <= max; i++){
              while(true){
                var tmp = this.intRandom(min, max);
                if(!m.includes(tmp)){
                  m.push(tmp);
                  break;
                }
              }
            }
          },

          /** min以上max以下の整数値の乱数を返す */
          intRandom(min, max){
            return Math.floor( Math.random() * (max - min + 1)) + min;
          },

          ///アニメ挙動//
          beforeEnter(el) {
            el.style.opacity = 0
            el.style.transform = 'translateY(100px)'
          },
          enter(el, done) {
            gsap.to(el, {
              opacity: 1,
              y: 0,
              delay: el.dataset.index * 0.15,
              onComplete: done
            })
          },
          leave(el, done) {
            gsap.to(el, {
              opacity: 0,
              y: 100,
              delay: el.dataset.index * 0.15,
              onComplete: done
            })
          }
        }
      })
      
    

ここのポイントは:

  • 関数handleScrollでスクロールイベントを発火させるトリガーをセットします。もちろんほかのスクロール系プラグインでセットするのも良いです。
  • 注意が必要なのは、v-show<li>に付与することです。筆者は<transition-group>v-showを当て、そもそもdisplay:noneの状態でoffsetTopを取れるはずないし
  • …初歩的なミスにだいぶハマってしまいました。

以上、「要素がふわっとランダムにfadeUpする」トランジションについてのVueの書き方でした!

この記事を書いた人

許綴綴

許綴綴

BU8-2所属のデザイナーです。メインの業務はデザイナーですが、フロントエンドが好きで普段色々と勉強しています。特にVue.jsを愛用し、最近はJamstackで自作CMSを模索しています。

おすすめ記事

タグ

2020新卒バトンAdobe IllustratorBIツールCCDLab.CSSCSVDockerDXECExcelExcel関数GAGitGoogleAnalyticsGoogleデータポータルKubernetesLT会MAMembersDinerOJTPhotoshopPythonRubySDGsSEOSimilarWebSlackSNSSocial Art JapanプロジェクトSQLUIUXUXライティングUXリサーチVitePressVSCodeWeb3WebディレクションWebディレクターWebマーケティングWeb解析Well-beingWordPressアクセシビリティアナリティクスウェビナーエシカルエシカルファッションエンジニアオウンドメディアオンラインオンラインイベントお悩み相談室キャリアクライアントワークコーディングコミュニケーションコンテンツマーケティングコンペサービスサイト構造サステイナブルスウェーデンスキルアップセミナーソーシャルアーティストソーシャルクリエイターチームビルディングツールデータデータアナリストデータサイエンティストディレクションディレクターデザイナーデザインデンマークトンマナナレッジハックブームの裏側プランニングフレームワークプレゼンプログラミングプログラミング教育ブロックチェーンフロントエンドマーケターマーケティングマシンラーニングマネジメントスキルミーティングメタバースメンタルハックメンバーズメディカルマーケティングカンパニーメンバーズルーツカンパニーユーザーテストライティングラボ活動リサーチリモートワークショップワークスタイル事例仕事術仙台再生可能エネルギー分析効率化勉強会動画北欧医療業界品質管理営業地方金融企業学生向け広告運用提案数学新卒研修新規構築機械学習気候変動海洋プラスチック問題生産性生産性向上産学連携研修社会課題社会課題調査競技プログラミング脱炭素自動化ツール色彩検定製薬業界資格開発環境障がい者雇用