使用 Vue 实现 CSS 过渡与动画效果

一、基础使用

  • 通过 class 实现。
  • 动画
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    /* 动画 */
    @keyframes rightToLeft {
      0% {
        transform: translateX(100px);
      }
      50% {
        transform: translateX(50px);
      }
      100% {
        transform: translateX(0);
      }
    }
    .animation {
      animation: rightToLeft 3s;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return { 
          animate:{
            animation: false
          }
        };
      },
      methods:{
        handleClick(){
          this.animate.animation = !this.animate.animation;
        }
      },
      template: `
        <div :class='animate'>666666</div>
        <button @click=handleClick>动起来</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

  • 过渡
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    /* 过渡 */
    .transition {
      transition: background-color 3s ease;
    }

    .blue {
      background-color: blue;
    }

    .green {
      background-color: green;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          transition: {
            transition: true,
            blue: true,
            green: false
          }
        };
      },
      methods: {
        handleClick() {
          this.transition.blue = !this.transition.blue;
          this.transition.green = !this.transition.green;
        }
      },
      template: `
        <div :class='transition'>666666</div>
        <button @click=handleClick>变色</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

  • 通过 class 与 style 共同实现过渡
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    /* 过渡 */
    .transition {
      transition: background-color 3s ease;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          styleObj: {
            backgroundColor: 'blue'
          }
        };
      },
      methods: {
        handleClick() {
          if (this.styleObj.backgroundColor === 'blue') {
            this.styleObj.backgroundColor = 'green';
          } else {
            this.styleObj.backgroundColor = 'blue'
          }
        }
      },
      template: `
        <div class='transition' :style='styleObj'>666666</div>
        <button @click=handleClick>变色</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

二、使用 transition 标签实现

  • 过渡
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    /* 过渡 */
    /* 入场 */
    .v-enter-from {
      opacity: 0;
    }
    .v-enter-active {
      transition: opacity 3s ease-out;
    }
    .v-enter-to {
      opacity: 1;
    }
    /* 出场 */
    .v-leave-from {
      opacity: 1;
    }
    .v-leave-active {
      transition: opacity 3s ease-out;
    }
    .v-leave-to {
      opacity: 0;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    // 单元素,单组件的入场出场动画
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        }
      },
      template: `
        <transition>
          <div v-if='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

  • 动画,修改 transition 的name属性
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    /* 动画 */
    @keyframes shake {
      0% {
        transform: translateX(100px)
      }
      50% {
        transform: translateX(50px)
      }
      100% {
        transform: translateX(0)
      }
    }
    /* 
      transition 设置了 name 属性后,这里的 
      v-leave-active 需要修改为 my-leave-active
    */
    .my-leave-active {
      animation: shake .5s;
    }
    .my-enter-active {
      animation: shake .5s;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        }
      },
      template: `
        <transition name='my'>
          <div v-if='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

三、自定义过渡 class 类名

  • 我们可以通过以下 attribute 来自定义过渡类名:
    • enter-from-class
    • enter-active-class
    • enter-to-class
    • leave-from-class
    • leave-active-class
    • leave-to-class
  • 他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css. 结合使用十分有用。

示例:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
  />
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        }
      },
      template: `
        <transition 
          enter-active-class="animate__animated animate__bounceInRight"
          leave-active-class="animate__animated animate__bounceOutRight"
        >
          <div v-show='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

四、动画和过渡一起进行

  • 通过 type 设置最终时长。
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
  <style>
    @keyframes shake {
      0% {
        transform: translateX(50px)
      }

      50% {
        transform: translateX(25px)
      }

      100% {
        transform: translateX(0)
      }
    }

    .v-enter-to {
      color: red;
    }

    .v-leave-to {
      color: red;
    }

    .v-enter-active {
      animation: shake 10s;
      transition: color 3s ease-in;
    }

    .v-leave-active {
      animation: shake 10s;
      transition: all 3s ease-in;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        }
      },
      template: `
        <transition type="transition">
          <div v-show='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

  • 通过 duration 设置最终时长。
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
  <style>
    @keyframes shake {
      0% {
        transform: translateX(50px)
      }

      50% {
        transform: translateX(25px)
      }

      100% {
        transform: translateX(0)
      }
    }

    .v-enter-to {
      color: red;
    }

    .v-leave-to {
      color: red;
    }

    .v-enter-active {
      animation: shake 3s;
      transition: color 1s ease-in;
    }

    .v-leave-active {
      animation: shake 3s;
      transition: all 1s ease-in;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        }
      },
      template: `
        <transition :duration="1000">
          <div v-show='show'>666666</div>
        </transition>
        <transition :duration="{ enter:500, leave:1500 }">
          <div v-show='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

五、使用 JavaScript 动画

  • 可以在 attribute 中声明 JavaScript 钩子
<transition
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @enter-cancelled="enterCancelled"
  @before-leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
  @leave-cancelled="leaveCancelled"
  <!-- 关闭css动画 -->
  :css="false"
>
</transition>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
        return {
          show: false
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        },
        handleBeforeEnter(el) {
          el.style.color = "red";
        },
        handleEnter(el, done) {
          const animation = setInterval(() => {
            const color = el.style.color;
            if (color === 'red') {
              el.style.color = 'green';
            } else {
              el.style.color = 'red';
            }
          }, 500)
          setTimeout(() => {
            clearInterval(animation);
            done();
          }, 3000)
        },
        handleAfterEnter(el) {
          el.style.color = "black";
          alert(666);
        },
        handleBeforeLeave(el) {
          el.style.backgroundColor = "red";
        },
        handleLeave(el, done) {
          const animation = setInterval(() => {
            const backgroundColor = el.style.backgroundColor;
            if (backgroundColor === 'red') {
              el.style.backgroundColor = 'green';
            } else {
              el.style.backgroundColor = 'red';
            }
          }, 500)
          setTimeout(() => {
            clearInterval(animation);
            done();
          }, 3000)
        },
        handleAfterLeave(el) {
          el.style.backgroundColor = 'white';
          alert(777);
        },
      },
      template: `
        <transition 
          :css="false"
          @before-enter="handleBeforeEnter"
          @enter="handleEnter"
          @after-enter="handleAfterEnter"
          @before-leave="handleBeforeLeave"
          @leave="handleLeave"
          @after-leave="handleAfterLeave"
        >
          <div v-show='show'>666666</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

六、多个单元素标签的切换

  • 可以设置 mode 改变过度模式,默认进入和离开是同时生效的。
  • in-out: 新元素先进行过渡,完成之后当前元素过渡离开。
  • out-in: 当前元素先进行过渡,完成之后新元素过渡进入。
  • 可以通过 appear attribute 设置节点在初始渲染的过渡。
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    .v-leave-to {
      opacity: 0;
    }

    .v-enter-from {
      opacity: 0;
    }

    .v-enter-active,
    .v-leave-active {
      transition: opacity 1s ease-in;
    }

    .v-leave-from,
    .v-enter-to {
      opacity: 1;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    // 多个单元素标签之间的切换
    const app = Vue.createApp({
      data() {
        return {
          show: true
        };
      },
      methods: {
        handleClick() {
          this.show = !this.show;
        },
      },
      template: `
        <transition mode='out-in' appear>
          <div v-if='show'>enter</div>
          <div v-else='show'>leave</div>
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

七、多个组件之间的过渡

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
  <style>
    .v-leave-to {
      opacity: 0;
    }

    .v-enter-from {
      opacity: 0;
    }

    .v-enter-active,
    .v-leave-active {
      transition: opacity 1s ease-in;
    }

    .v-leave-from,
    .v-enter-to {
      opacity: 1;
    }
  </style>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    // 多个单组件之间的切换
    const ComponentA = {
      template: '<div>hello world</div>'
    }

    const ComponentB = {
      template: '<div>bye world</div>'
    }
    const app = Vue.createApp({
      data() {
        return { component: 'component-a' };
      },
      methods: {
        handleClick() {
          if (this.component === 'component-a') {
            this.component = 'component-b';
          } else {
            this.component = 'component-a';
          }
        },
      },
      components: {
        'component-a': ComponentA,
        'component-b': ComponentB,
      },
      template: `
        <transition mode='out-in' appear>
          <component :is="component" />
        </transition>
        <button @click=handleClick>切换</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

八、状态动画

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>使用 Vue 实现 CSS 过渡与动画效果</title>
</head>

<body>
  <div id="root">
  </div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    // 状态动画
    const ComponentA = {
      template: '<div>hello world</div>'
    }

    const ComponentB = {
      template: '<div>bye world</div>'
    }
    const app = Vue.createApp({
      data() {
        return {
          num: 1,
          maxNum: 10
        };
      },
      methods: {
        handleClick() {
          if (this.num < this.maxNum) {
            const animation = setInterval(() => {
              this.num++;
              if (this.num === this.maxNum) {
                clearInterval(animation);
              }
            }, 100);
          }
        },
      },
      template: `
        <div>{{num}}</div>
        <button @click=handleClick>增加</button>
      `
    });
    const vm = app.mount('#root');
  </script>
</body>

</html>

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值