Vue3_08(动画)

Vue的transition动画

可以给下列情形中任何元素和组件添加进入/离开过渡:【无name则默认以v开头,v-enter-from,v-enter-to,v-enter-active,v-leave-from,v-leave-to,v-leave-active】

  条件渲染 (使用 v-if)条件展示 (使用 v-show)
  动态组件
  组件根节点

通过transition来实现的动画效果 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<transition name="seal">
      <h2 v-if="isShow">Hello World</h2>
</transition>
 
<style scoped>
  .seal-enter-from,
  .seal-leave-to {
    opacity: 0;
  }
 
  .seal-enter-to,
  .seal-leave-from {
    opacity: 1;
  }
 
  .seal-enter-active,
  .seal-leave-active {
    transition: opacity 2s ease;
  }
</style>

 通过animation来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<transition name="seal">
      <h2 class="title" v-if="isShow">Hello World</h2>
</transition>
 
<style scoped>
  .seal-enter-active {
    animation: bounce 1s ease;
  }
 
  .seal-leave-active {
    animation: bounce 1s ease reverse;
  }
 
  @keyframes bounce {
    0% {
      transform: scale(0)
    }
 
    50% {
      transform: scale(1.2);
    }
 
    100% {
      transform: scale(1);
    }
  }
</style>

同时设置过渡和动画Vue为了知道过渡的完成,内部是在监听 transitionend 或 animationend,到底使用哪一个取决于元素应用的CSS规则。

  设置 type 属性为 animation 或者 transition 来明确的告知Vue监听的类型

  设置过渡的时间 duration,number类型:同时设置进入和离开的过渡时间,object类型:分别设置进入和离开的过渡时间

1
2
3
<transition name="why" type="transition" :duration="{enter: 800, leave: 1000}">
      <h2 class="title" v-if="isShow">Hello World</h2>
</transition>

 过渡的模式mode

两个元素切换不设置mode会同时进行,若设置 in-out: 新元素先进行过渡,完成之后当前元素过渡离开;out-in: 当前元素先进行过渡,完成之后新元素过渡进入;

1
2
3
4
<transition name="seal" mode="out-in">
      <h2 class="title" v-if="isShow">Hello World</h2>
      <h2 class="title" v-else>你好啊,李银河</h2>
</transition>

appear初次渲染

1
2
3
<transition name="why" mode="out-in" appear>
      <component :is="isShow ? 'home': 'about'"></component>
</transition>

 animate.css库的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#安装
npm install animate.css
#main.js中引入
import "animate.css";
#用法一:bounceInUp为animate样式
<style scoped>
  .why-enter-active {
    animation: bounceInUp 1s ease-in;
  }
 
  .why-leave-active {
    animation: bounceInUp 1s ease-in reverse;
  }
</style>
#用法二
#直接引用样式animate__animated animate__fadeInDown animate__flipInY
<transition enter-active-class="animate__animated animate__fadeInDown"
                  eave-active-class="animate__animated animate__flipInY">
      <h2 class="title" v-if="isShow">Hello World</h2>
</transition>

gsap库的使用

前置:transition组件给我们提供的JavaScript钩子,这些钩子可以帮助我们监听动画执行到什么阶段

当我们使用JavaScript来执行过渡动画时,需要进行 done 回调,否则它们将会被同步调用,过渡会立即完成。
添加 :css="false",也会让 Vue 会跳过 CSS 的检测,除了性能略高之外,这可以避免过渡过程中 CSS 规则的影响。

结合gsap使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<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: {
      enter(el, done) {
        console.log("enter");
        gsap.from(el, {
          scale: 0,
          x: 200,
          onComplete: done
        })
      },
      leave(el, done) {
        console.log("leave");
        gsap.to(el, {
          scale: 0,
          x: 200,
          onComplete: done
        })
      }
    }
  }
</script>

gsap实现数字变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
  <div class="app">
    <input type="number" step="100" v-model="counter">
    <h2>当前计数: {{showNumber.toFixed(0)}}</h2>
  </div>
</template>
 
<script>
  import gsap from 'gsap';
 
  export default {
    data() {
      return {
        counter: 0,
        showNumber: 0
      }
    },
    watch: {
      counter(newValue) {
        gsap.to(this, {duration: 1, showNumber: newValue})
      }
    }
  }
</script>

列表渲染,并且该列表中添加删除数据希望有动画执行,需要使用<transition-group>

  默认情况下,它不会渲染一个元素的包裹器,但是你可以指定一个元素并以 tag attribute 进行渲染;
  过渡模式不可用,因为我们不再相互切换特有的元素;
  内部元素总是需要提供唯一的 key attribute 值;
  CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<template>
  <div>
    <button @click="addNum">添加数字</button>
    <button @click="removeNum">删除数字</button>
    <button @click="shuffleNum">数字洗牌</button>
 
    <transition-group tag="p" name="seal">
      <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;
  }
 
  .seal-enter-from,
  .seal-leave-to {
    opacity: 0;
    transform: translateY(30px);
  }
 
  .seal-enter-active,
  .seal-leave-active {
    transition: all 1s ease;
  }
 
  .seal-leave-active {
    position: absolute;
  }
 
  .seal-move {
    transition: transform 1s ease;
  }
</style>

列表的交替动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<template>
  <div>
    <input v-model="keyword">
    <transition-group tag="ul" name="seal" :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", "seal", "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>

  

posted @   Hexrui  阅读(88)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
返回顶部
点击右上角即可分享
微信分享提示