vue过渡&动画&Animate.css动画库(2)

前言:

这篇文章是基于vue过渡&动画&Animate.css动画库(1)

继续编写的。

初始渲染时的过渡

简介

可以通过 appear 设置节点在初始渲染的过渡

<transition appear>
  <!-- ... -->
</transition>

案例:

<div class="a1">
    <button @click="but=!but">点我 </button>
    <transition enter-active-class="animate__animated animate__rollIn"
        leave-active-class="animate__animated animate__rollOut" appear>
        <div class="box" v-if="but"></div>
    </transition>
</div>

效果:(刷新页面初始化渲染)

单组件的过渡

简介

在<transition>中的元素为一个子组件

案例

 父组件中定义:

<div>
    <button @click="but=!but">点我 </button>
    <transition enter-active-class="animate__animated animate__rollIn"
        leave-active-class="animate__animated animate__rollOut" appear>
        <div class="box" v-if="but"></div>
    </transition>
</div>

子组件:

<template>
  <div class="about"></div>
</template>
<style lang="less" scoped>
.about {
  width: 200px;
  height: 200px;
  background-color: red;
}
</style>

效果:

多个元素的过渡

简介

对于原生标签可以使用 v-if/v-else。最常见的多标签过渡是一个列表和描述这个列表为空消息的元素

案例

<template>
  <div>
    <button @click="add">Add</button>
    <div>
      <transition name="fade">
        <ul v-if="items.length > 0" key="ul">
          <li v-for="(item, index) in items" :key="index">{{ item }}</li>
        </ul>
        <p key="empty" v-else>数组中没有任何元素</p>
      </transition>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      items: [],
    };
  },
  methods: {
    add() {
      this.items.push(4);
    },
  },
};
</script>
<style scoped>
.fade-enter-active {
  position: absolute;
  animation: bounceInLeft 1s;
}
.fade-leave-active {
  position: absolute;
  animation: bounceOutRight 1s;
}

@keyframes bounce-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

效果:

注意: 当有相同标签名的元素切换时,需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践。

过渡模式 

  • in-out新元素先进行过渡,完成之后当前元素过渡离开。

  • out-in当前元素先进行过渡,完成之后新元素过渡进入。

案例2

<template>
  <div>
    <div>
      <button @click="payMethod = 'wechat'">微信支付</button>
      <button @click="payMethod = 'alipay'">支付宝支付</button>
    </div>
    <transition name="fade">
      <img :key="payMethod" :src="payMethod === 'wechat' ? wechat : alipay" alt="" />
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      payMethod: "wechat",
      wechat:
        "https://img1.baidu.com/it/u=1320610702,3769627335&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=317",
      alipay:
        "https://img2.baidu.com/it/u=3840063115,3619456710&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500",
    };
  },
};
</script>
<style scoped>
.fade-enter-active {
  /* animation: bounceInLeft 1s; */
  animation: bounce-in 1s;
}
.fade-leave-active {
  /* animation: bounceOutRight 1s; */
  animation: bounce-in 1s reverse;
}

@keyframes bounce-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

效果:

此时的效果时非常不美好的, 两个img都被重绘了,一个离开过渡的时候另一个开始进入过渡。这是 <transition> 的默认行为 - 进入和离开同时发生。

我们可以使用out-in过渡模式:

<transition name="fade" mode="out-in">
  <img :key="payMethod" :src="payMethod === 'wechat' ? wechat : alipay" alt="" />
</transition>

效果:

多组件过渡 

简介

多个组件的过渡简单很多 - 我们不需要使用 key attribute。相反,我们只需要使用动态组件

案例

<template>
  <div>
    <nav>
      <input type="radio" name="" id="man" value="Man" v-model="gender" />
      <label for="man">男</label>
      <input type="radio" name="" id="woman" value="Woman" v-model="gender" />
      <label for="woman">女</label>
    </nav>
    <div>
      <transition name="fade" mode="out-in">
        <component :is="gender"></component>
      </transition>
    </div>
  </div>
</template>
<script>
import Man from "./Man.vue";
import Woman from "./Woman.vue";
export default {
  data() {
    return {
      gender: "Man",
    };
  },
  components: {
    Man,
    Woman,
  },
};
</script>
<style scoped>
.fade-enter-active {
  /* animation: bounceInLeft 1s; */
  animation: bounce-in 1s;
}
.fade-leave-active {
  /* animation: bounceOutRight 1s; */
  animation: bounce-in 1s reverse;
}

@keyframes bounce-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

子组件Woman

<template>
    <h1>我是女孩</h1>
</template>

子组件Man 

<template>
    <h1>我是男孩</h1>
</template>

效果:

列表的过渡

简介

如何同时渲染整个列表(<transition>内有多个元素),比如使用 v-for?在这种场景中,使用 <transition-group> 组件。在我们深入例子之前,先了解关于这个组件的几个特点:

  • 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>。你也可以通过 tag attribute 更换为其他元素。
  • 过渡模式不可用,因为我们不再相互切换特有的元素。
  • 内部元素总是需要提供唯一的 key attribute 值。
  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。

列表的进入/离开过渡

let app = new Vue({
    el: '#app',
    data: {
        items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
        nextNum: 10
    },
    methods: {
        randomIndex: function () {
            return Math.floor(Math.random() * this.items.length)
        },
        add: function () {
            this.items.splice(this.randomIndex(), 0, this.nextNum++)
        },
        remove: function () {
            this.items.splice(this.randomIndex(), 1)
        },
    }
})
<div id="list-demo" class="demo">
    <button v-on:click="add">Add</button>
    <button v-on:click="remove">Remove</button>
    <transition-group name="list" tag="p">
        <span v-for="item in items" v-bind:key="item" class="list-item">
            {{ item }}
        </span>
    </transition-group>
</div>

.list-item {
    display: inline-block;
    margin-right: 10px;
}

.list-enter-active,
.list-leave-active {
    transition: all 1s;
}

.list-enter,
.list-leave-to {
    opacity: 0;
    transform: translateY(30px);
}

 效果

v-move

简介

从上面例子有个问题,当添加和移除元素的时候,周围的元素会瞬间移动到他们的新布局的位置,而不是平滑的过渡,使用 v-move 类就可以解决这个问题:

利用v-move现实过渡增加删除

.list-item {
    display: inline-block;
    margin-right: 10px;
}

.list-enter-active,
.list-leave-active {
    transition: all 1s;
}

.list-enter,
.list-leave-to {
    opacity: 0;
    transform: translateY(30px);
}
//控制删除时的动画效果
.list-leave-active {
    position: absolute;
}
//控制添加时的动画效果
.list-move {
    transition: transform 1s;
}

效果(是不是这样看起来更加丝滑了很多)

 利用v-move现实乱序并过渡

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="flip-list-demo" class="demo">
    <button v-on:click="shuffle">Shuffle</button>
    <transition-group name="flip-list" tag="ul">
        <li v-for="item in items" v-bind:key="item">
            {{ item }}
        </li>
    </transition-group>
</div>iv>    
data: {
    items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
},
methods: {
    shuffle: function () {
        this.items = _.shuffle(this.items)
    }
}
.flip-list-move {
    transition: transform 1s;
}

效果:

 这个看起来很神奇,这个案例引用了 Lodash.js 中的 _.shuffle()方法打乱了列表各个元素顺序,加上v-move使用 transforms 将元素从之前的位置平滑过渡新的位置。关于Lodash.js的使用官网写的很详细,可以自己去看。

利用v-move现实图片乱序过渡

当然这个我们可以利用上个案例所学做出更加炫酷的效果(和上面代码换汤不换药)

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="flip-list-demo" class="demo">
    <button v-on:click="shuffle">Shuffle</button>
    <transition-group name="flip-list" tag="div">
        <img :src="item" alt="" v-for="item in items" :key="item">
    </transition-group>
</div>
data: {
    items: [
        './imgs/1.webp',
        './imgs/2.webp',
        './imgs/3.webp',
        './imgs/4.webp',
        './imgs/5.webp',
        './imgs/6.webp',
        './imgs/7.webp',
        './imgs/8.webp',
        './imgs/9.webp',
    ],
},
methods: {
    shuffle: function () {
        this.items = _.shuffle(this.items)
    }
}
img {
    width: 200px;
    height: 200px;
}

.flip-list-move {
    transition: transform 1s;
}

.demo div {
    width: 600px;

}

效果:

多维网格过渡

这里需要注意key的唯一性,许多同学在这里栽坑

<div id="list-demo" class="demo">
    <button v-on:click="shuffle">Shuffle</button>
    <transition-group name="list" tag="div" class="list-div">
        <div v-for="item in items" v-bind:key="item" class="list-item">{{ item[0]}}</div>
    </transition-group>
</div>
data: {
    items: [[1, 1], [2, 1], [3, 1], [4, 1], [2, 2], [1, 2], [4, 2], [3, 2], [4, 3], [2, 3], [3, 3], [1, 3], [3, 4], [4, 4], [1, 4], [2, 4]]
},
methods: {
    shuffle: function () {
        this.items = _.shuffle(this.items)
    }
}
.list-item {
    display: inline-block;
    height: 20px;
    width: 20px;
    border: 1px solid #ccc;
}
.list-enter-active,
.list-leave-active {
    transition: all 1s;
}
.list-enter,
.list-leave-to {
    opacity: 0;
}
.list-div {
    width: 90px;
}
.list-move{
   transition: transform 1s;
}

效果:

 需要注意的是使用 FLIP 过渡的元素不能设置为 display: inline 。作为替代方案,可以设置为 display: inline-block 或者放置于 flex 中

状态过渡

简介

Vue 的过渡系统提供了非常多简单的方法设置进入、离开和列表的动效。那么对于数据元素本身的动效呢,比如:

  • 数字和运算
  • 颜色的显示
  • SVG 节点的位置
  • 元素的大小和其他的 property

这些数据要么本身就以数值形式存储,要么可以转换为数值。有了这些数值后,我们就可以结合 Vue 的响应式和组件系统,使用第三方库来实现切换元素的过渡状态

gsap.js

简介:一个“轻量级”、“高效率”、强大的2D动画引擎

先介绍一个 gsap 基础函数:
    gsap.to(targets, second, options)
targets :元素节点或者选择器字符串(如 .className )
second :动画执行秒数
options :动画末状态的配置对象(所有可用选项详见 CSSPlugin )
 

案例:

<div>
    <input v-model.number="number" type="number" step="20">
    <p>{{ animatedNumber }}</p>
</div>
data: {
    number: 0,
    tweenedNumber: 0
},
computed: {
    animatedNumber: function () {
        return this.tweenedNumber.toFixed(0);
    }
},
watch: {
    number: function (newValue) {
        gsap.to(this.$data, 0.5, { tweenedNumber: newValue });
    }
}

效果:

路由过渡

简介

简单来说就是路由之间的过渡效果与组件过渡差不多,话不多说,上案例

案例

先看router, 在B路由中有两个子路由:A,C

B路由展示:

<template>
  <div>
    <router-link to="/A">点击进入A路由</router-link>
    <router-link to="/C">点击进入C路由</router-link>
    <transition appear mode="out-in">
      <router-view></router-view>
    </transition>
  </div>
</template>
<script>
export default {};
</script>
<style lang="less" scoped>
a {
  margin: 0 60px;
}
.v-enter-active {
  animation: fade 0.5s;
}
.v-leave-active {
  animation: fade 0.5s reverse;
}
@keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

A,C路由展示:

<template>
  <div key="diaa">我是AAAAA</div>
</template>
<template>
  <div key="diaa">我是CCCCC</div>
</template>

效果:

 

待续(学到知识的不妨点个赞)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值