vue中的過渡動畫

前言

記一次vue 組件中使用 transition 和 transition-group 設置過渡動畫,總結來說可分爲分爲 name 版, js 鉤子操作類名版, js 鉤子操作行內樣式版...

template模板結構

  // 單個元素
    <transition name="自定義名字">
      <p v-if="show">hello</p>
    </transition>
  // 列表元素: 注意group的直接子元素是v-for渲染出來的
    <ul class="list">
      <transition-group name="list">
        <li v-for="(item, index) in gameList" :key="item.id">
          <app-horizontal :itemData="item"></app-horizontal>
        </li>
      </transition-group>
    </ul>

name 版,name 爲組件中的屬性

出現的過程: name-enter(初始態) => name-enter-active(中間態) => name-enter-to(終止態)
消失的過程: name-leave => name-leave-active => name-leave-to

以進場過渡動畫爲例子

我們可以分別設置 enter 階段 和 enter-to 階段的動畫
  1.設置進入時需要過渡的屬性
  .name-enter
  {
    opacity: 0;
    transform: translateY(30px)
  }
  2.然後在 name-enter-active中設置過渡時間
  .name-enter-active {
    transition: all .3s;
  }
  3.最後在 name-enter-to 中寫上終止態屬性
    其實終止態的opacity: 1;transform: none; 是默認的,可以不用寫
  .name-enter-to {
    opacity: 1;
    transform: translateY(0);
  }
  如果要給列表中的元素設置交錯的效果, 元素不多的話可以添加 delay 屬性
  .name-enter-active:nth-child(3n+1) {
    transition-delay: 0s;
  }
  .name-enter-active:nth-child(3n+2) {
    transition-delay: .1s;
  }
  .name-enter-active:nth-child(3n+3) {
    transition-delay: .2s;
  }
  離場動畫同理...

js 鉤子實現過渡動畫: 通過操作類名; 就是 name 版的 js 實現

// 例如實現上述列表依次顯示
  <ul class="list">
    <transition-group
      v-bind:css="false"
      v-on:before-enter="beforeEnter"
      v-on:enter="enter"
      v-on:after-enter="afterEnter">
      <li v-for="(item, index) in gameList" 
        :key="item.id" 
        :data-delay="index*100" 
      >
          <app-horizontal :itemData="item"></app-horizontal>
      </li>
    </transition-group>
  </ul>  
  // 
  methods: {
    // 事先定義上述類名
    // 在beforeEnter enter afterEnter 鉤子中手動操作上述類名
    
    // 初始態
    beforeEnter(dom) {
      dom.classList.add('list-enter', 'list-enter-active');
    },
    // 中間態
    enter(dom,done) {
      // 通過 setTimeout + dataset 實現過渡
      let delay = dom.dataset.delay;
      setTimeout(function () {
        dom.classList.remove('list-enter');
        dom.classList.add('list-enter-to');
        //監聽 transitionend 事件
        var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
        dom.addEventListener(transitionend, function onEnd() {
          // 移除事件
          dom.removeEventListener(transitionend, onEnd);
          //調用done(),表示動畫已完成
          done()
        });
      }, delay)
    },
    // 終止態
    afterEnter(dom) {
      dom.classList.remove('list-enter-to', 'list-enter-active');
    }
  }

js 鉤子過渡動畫: 通過操作行內屬性, 自定義動畫

   <ul class="list">
    <transition-group
      v-bind:css="false"
      v-on:before-enter="beforeEnter"
      v-on:enter="enter"
      v-on:after-enter="afterEnter">
      <li v-for="(item, index) in gameList" 
        :key="item.id" 
        :data-delay="index*100"
        data-y = "100%" 
      >
          <app-horizontal :itemData="item"></app-horizontal>
      </li>
    </transition-group>
  </ul>  
  // 對應的操作方法; 添加自定義的 dataset,給dom設置css樣式;根據需求添加
   methods: {
     // 初始態
    beforeEnter(dom) {
      let { x = 0, y = 0, opacity = 0 } = dom.dataset;
      dom.style.cssText = `transition: .3s;opacity: ${opacity};transform: translateX(${x}) translateY(${y});`;
    },
    // 中間態
    enter(dom,done) {
      let delay = dom.dataset.delay;
      setTimeout(function () {
        dom.style.cssText = `transition: .3s;opacity: 1;transform: translateX(0) translateY(0);`;
        //監聽 transitionend 事件
        var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
        dom.addEventListener(transitionend, function onEnd() {
             dom.removeEventListener(transitionend, onEnd);
             done(); 
        });
      }, delay)
    },
    // 終止態
    afterEnter(dom) {
      dom.style.cssText = "";
    }
  }

這裏記錄一下監聽css3的animation動畫和transition事件:

webkit-animation動畫有三個事件:
    開始事件: webkitAnimationStart
    結束事件: webkitAnimationEnd
    重複運動事件: webkitAnimationIteration

css3的過渡屬性transition: 一個事件
    過渡結束: webkitTransitionEnd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章