zoukankan      html  css  js  c++  java
  • 684 Vue3过渡、动画:transition,transition-group,过渡动画class,animate.css,gsap,列表的过渡

    认识动画


    Vue的transition动画


    Transition组件的原理


    过渡动画class


    class添加的时机和命名规则


    过渡css动画


    同时设置过渡和动画


    显示的指定动画时间


    过渡的模式mode


    动态组件的切换


    appear初次渲染


    01_过渡动画的使用.vue

    <template>
      <div>
        <button @click="isShow = !isShow">显示/隐藏</button>
    
        <transition name="why">
          <h2 v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
      };
    </script>
    
    <style scoped>
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      /* 【在浏览器中的默认值就1,所以可以不写,删掉】 */
      .why-enter-to,
      .why-leave-from {
        opacity: 1;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 2s ease;
      }
    </style>
    

    02_animation动画.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <transition name="why">
          <h2 class="title" v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
      };
    </script>
    
    <style scoped>
      .app {
         200px;
        margin: 0 auto;
      }
    
      .title {
        display: inline-block;
      }
    
      .why-enter-active {
        animation: bounce 1s ease;
      }
    
      .why-leave-active {
        animation: bounce 1s ease reverse;
      }
    
      @keyframes bounce {
        0% {
          transform: scale(0);
        }
    
        50% {
          transform: scale(1.2);
        }
    
        100% {
          transform: scale(1);
        }
      }
    </style>
    

    03_type和duration属性.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <!-- :duration的值也可以是数字 -->
        <transition
          name="why"
          type="transition"
          :duration="{ enter: 800, leave: 1000 }"
        >
          <h2 class="title" v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
      };
    </script>
    
    <style scoped>
      .app {
         200px;
        margin: 0 auto;
      }
    
      .title {
        display: inline-block;
      }
    
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 1s ease;
      }
    
      .why-enter-active {
        animation: bounce 1s ease;
      }
    
      .why-leave-active {
        animation: bounce 1s ease reverse;
      }
    
      @keyframes bounce {
        0% {
          transform: scale(0);
        }
    
        50% {
          transform: scale(1.2);
        }
    
        100% {
          transform: scale(1);
        }
      }
    </style>
    

    04_两个元素切换mode.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <transition name="why" mode="out-in">
          <h2 class="title" v-if="isShow">Hello World</h2>
          <h2 class="title" v-else>你好啊,哈哈</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
      };
    </script>
    
    <style scoped>
      .app {
         200px;
        margin: 0 auto;
      }
    
      .title {
        display: inline-block;
      }
    
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 1s ease;
      }
    
      .why-enter-active {
        animation: bounce 1s ease;
      }
    
      .why-leave-active {
        animation: bounce 1s ease reverse;
      }
    
      @keyframes bounce {
        0% {
          transform: scale(0);
        }
    
        50% {
          transform: scale(1.2);
        }
    
        100% {
          transform: scale(1);
        }
      }
    </style>
    

    05_动态组件的切换.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <transition name="why" mode="out-in" appear>
          <component :is="isShow ? 'home': 'about'"></component>
        </transition>
      </div>
    </template>
    
    <script>
      import Home from './pages/Home.vue';
      import About from './pages/About.vue';
    
      export default {
        components: {
          Home,
          About
        },
        data() {
          return {
            isShow: true
          }
        }
      }
    </script>
    
    <style scoped>
      .app {
         200px;
        margin: 0 auto;
      }
    
      .title {
        display: inline-block;
      }
    
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 1s ease;
      }
    
      .why-enter-active {
        animation: bounce 1s ease;
      }
    
      .why-leave-active {
        animation: bounce 1s ease reverse;
      }
    
      @keyframes bounce {
        0% {
          transform: scale(0)
        }
    
        50% {
          transform: scale(1.2);
        }
    
        100% {
          transform: scale(1);
        }
      }
    </style>
    

    认识animate.css


    自定义过渡class


    animate.css库的使用


    01_结合animate使用.vue

    <template>
      <div class="app">
        <div>
          <button @click="isShow = !isShow">显示/隐藏</button>
        </div>
    
        <transition
          enter-active-class="animate__animated animate__fadeInDown"
          leave-active-class="animate__animated animate__flipInY"
        >
          <h2 class="title" v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
      };
    </script>
    
    <style scoped>
      .title {
        display: inline-block;
        transform: translateX(100px);
      }
    
      .animate__flipInY {
        animation-direction: reverse;
      }
    
      /* .why-enter-active {
        animation: bounceInUp 1s ease-in;
      }
    
      .why-leave-active {
        animation: bounceInUp 1s ease-in reverse;
      } */
    </style>
    

    认识gsap库


    JavaScript钩子


    gsap库的使用


    gsap实现数字变化


    02_生命周期钩子.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <transition
          @before-enter="beforeEnter"
          @enter="enter"
          @after-enter="afterEnter"
          @before-leave="beforeLeave"
          @leave="leave"
          @afterLeave="afterLeave"
        >
          <h2 class="title" v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            isShow: true,
          };
        },
        methods: {
          // 【注意,这些生命周期钩子放在methods,而不是像vue的生命周期钩子那样。】
          // 对应from,做一些初始化操作
          beforeEnter() {
            console.log("beforeEnter");
          },
          // 相当于active,执行具体的动画
          enter() {
            console.log("enter");
          },
          // 做收尾工作
          afterEnter() {
            console.log("afterEnter");
          },
          beforeLeave() {
            console.log("beforeLeave");
          },
          leave() {
            console.log("leave");
          },
          afterLeave() {
            console.log("afterLeave");
          },
        },
      };
    </script>
    
    <style scoped>
      .title {
        display: inline-block;
      }
    </style>
    

    03_结合gsap使用.vue

    <template>
      <div class="app">
        <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    
        <transition @enter="enter" @leave="leave" :css="false">
          <h2 class="title" v-if="isShow">Hello World</h2>
        </transition>
      </div>
    </template>
    
    <script>
      import gsap from "gsap";
    
      export default {
        data() {
          return {
            isShow: true,
          };
        },
        methods: {
          toggle() {
            this.isShow = !this.isShow
          },
          enter(el, done) {
            console.log("enter");
            // from:从什么达到默认状态,{}写初始状态,一直达到h2本该有的默认状态
            gsap.from(el, {
              scale: 0,
              x: 500,
              onComplete: done,
            });
          },
          leave(el, done) {
            console.log("leave");
            // to:执行动画要达到的状态
            gsap.to(el, {
              scale: 0,
              x: 200, // 从200过来的,重新回到200
              onComplete: done,
            });
          },
        },
      };
    </script>
    
    <style scoped>
      .title {
        display: inline-block;
        font-size: 30px;
      }
    </style>
    

    04_gsap数字递增动画.vue

    <template>
      <div class="app">
        <input type="number" step="100" v-model="counter" />
        <h2>当前计数: {{showCounter}}</h2>
        <h2>当前计数: {{ showNumber.toFixed(0) }}</h2>
      </div>
    </template>
    
    <script>
      import gsap from "gsap";
    
      export default {
        data() {
          return {
            counter: 0,
            showNumber: 0,
          };
        },
        // 也可以不用计算属性
        computed: {
          showCounter() {
            return this.showNumber.toFixed(0);
          }
        },
        watch: {
          counter(newValue) {
            gsap.to(this, {
              duration: 1,
              showNumber: newValue,
              // 这里不能这样写,因为是在watch里,会时时监听num的改变,然后绑定到界面上,而computed里是等数据更新完毕了,最后才会绑定到界面上
              // showNumber: Number(newValue).toFixed(0),
            });
          },
        },
      };
    </script>
    
    <style scoped></style>
    

    认识列表的过渡


    列表过渡的基本使用


    列表过渡的移动动画


    01_transition-group的使用.vue

    <template>
      <div>
        <button @click="addNum">添加数字</button>
        <button @click="removeNum">删除数字</button>
        <button @click="shuffleNum">数字洗牌</button>
    
        <transition-group tag="p" name="why">
          <span v-for="item in numbers" :key="item" class="item">
            {{ item }}
          </span>
        </transition-group>
      </div>
    </template>
    
    <script>
      import _ from "lodash";
    
      export default {
        data() {
          return {
            numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
            numCounter: 10,
          };
        },
        methods: {
          addNum() {
            // this.numbers.push(this.numCounter++)
            this.numbers.splice(this.randomIndex(), 0, this.numCounter++);
          },
          removeNum() {
            this.numbers.splice(this.randomIndex(), 1);
          },
          shuffleNum() {
            this.numbers = _.shuffle(this.numbers);
          },
          randomIndex() {
            return Math.floor(Math.random() * this.numbers.length);
          },
        },
      };
    </script>
    
    <style scoped>
      .item {
        margin-right: 10px;
        display: inline-block;
      }
    
      /* 初始化 */
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
        transform: translateY(30px);
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: all 1s ease;
      }
    
      .why-leave-active {
        /* 离开动画生效时,绝对定位就会脱离标准流 */
        position: absolute;
      }
    
      /* 【删除数字时,列表也做动画。】 */
      .why-move {
        transition: transform 1s ease;
      }
    </style>
    

    列表的交错过渡案例


    02_列表的交替动画.vue

    <template>
      <div>
        <input v-model="keyword" />
        <transition-group
          tag="ul"
          name="why"
          :css="false"
          @before-enter="beforeEnter"
          @enter="enter"
          @leave="leave"
        >
          <li v-for="(item, index) in showNames" :key="item" :data-index="index">
            {{ item }}
          </li>
        </transition-group>
      </div>
    </template>
    
    <script>
      import gsap from "gsap";
    
      export default {
        data() {
          return {
            names: ["abc", "cba", "nba", "why", "lilei", "hmm", "kobe", "james"],
            keyword: "",
          };
        },
        computed: {
          showNames() {
            return this.names.filter((item) => item.indexOf(this.keyword) !== -1);
          },
        },
        methods: {
          beforeEnter(el) {
            el.style.opacity = 0;
            el.style.height = 0;
          },
          enter(el, done) {
            gsap.to(el, {
              opacity: 1,
              height: "1.5em",
              delay: el.dataset.index * 0.5,
              onComplete: done,
            });
          },
          leave(el, done) {
            gsap.to(el, {
              opacity: 0,
              height: 0,
              delay: el.dataset.index * 0.5,
              onComplete: done,
            });
          },
        },
      };
    </script>
    
    <style scoped>
      /* 要把css动画注释掉 */
      /* .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 1s ease;
      } */
    </style>
    
  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
    2. Add Two Numbers
    链式表的按序号查找
    可持久化线段树——区间更新hdu4348
    主席树——树链上第k大spoj COT
  • 原文地址:https://www.cnblogs.com/jianjie/p/14878990.html
Copyright © 2011-2022 走看看