多元素/组件切换动画&列表动画&状态动画

389 阅读2分钟

多个单元素切换显示的动画

基础使用

eg: 为两个单元素的切换显示,添加动画效果

同之前单元素的过渡和动画一样,使用transition配合vue为我们提供的固定的class

敲代码

<style>
   .v-enter-from,
   .v-leave-to{
    opacity: 0;
   }
   .v-enter-active,
   .v-leave-active
   {
    transition: opacity 2s ease-in;
   }
   .v-enter-to,
   .v-leave-from{
    opacity: 1;
   }
 </style>
  <script>
    const app = Vue.createApp({
        data() {
            return {
                show: true
            }
        },
        methods: {
            handleClick() {
                this.show  = !this.show
            },
        },
        template: `
        <div>
            <transition>
                <div v-if="show">hello world</div>
                <div v-else="show">bye world</div>
            </transition>
            <button @click="handleClick">切换</button>
        </div>
        `
    })

    const vm = app.mount('#root')
</script>

运行结果

6.gif

但是这种动画看起来很不自然,一般要等bye world先彻底隐藏之后hello world才慢慢展示,而不是一边隐藏一边展示

添加mode="out-in"

transition上添加mode="out-in"的意思是先让元素隐藏完成再显示,即“先出再入”。mode还有一个值mode="in-out"它的意思是先让元素显示完成再隐藏,即“先入再出”。如果不使用mode那么显示和隐藏的动画默认是同步执行的

敲代码

// 其他相同代码省略
template: `
    <div>
        <transition mode="out-in">
            <div v-if="show">hello world</div>
            <div v-else="show">bye world</div>
        </transition>
        <button @click="handleClick">切换</button>
    </div>

【**运行结果**】

7.gif

初次加载内容的时候就想有动画效果?

只需要在transition标签上添加appear属性即可

敲代码

 // 其他相同代码省略
template: `
    <div>
        <transition mode="out-in" appear>
            <div v-if="show">hello world</div>
            <div v-else="show">bye world</div>
        </transition>
        <button @click="handleClick">切换</button>
    </div>
    `

运行结果

8.gif

多个单组件切换显示的动画

1. 使用v-if和v-else的方式实现

敲代码

 const ComponentA = {
            template: `<div>hello world</div>`
        }
const ComponentB = {
    template: `<div>Bye world</div>`
}
const app = Vue.createApp({
    data() {
        return {
            show: true
        }
    },
    methods: {
        handleClick() {
            this.show = !this.show
        },
    },
    components: {
        "component-a": ComponentA,
        "component-b": ComponentB
    },
    template: `
    <div>
        <transition mode="out-in" appear>
            <component-a v-if="show"/>
            <component-b v-else="show"/>
        </transition>
        <button @click="handleClick">切换</button>
    </div>
    `
})

const vm = app.mount('#root')

2. 使用动态组件的方式实现

敲代码

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: `
    <div>
        <transition mode="out-in" appear>
            <component :is="component"/>
        </transition>
        <button @click="handleClick">切换</button>
    </div>
    `
})

const vm = app.mount('#root')

列表动画

基础使用

敲代码

.v-enter-from {
    opacity: 0;
    transform: translateY(30px);
 }

.v-enter-active{
    transition: all 1s ease-in;
}

.v-enter-to{
    opacity: 1;
    transform: translateY(0px);
}

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

运行结果

9.gif

备注

想要给列表添加动画,就要在列表的外层包裹<transition-group></transition-group>标,再配合vue为我们提供的class完成列表动画

.v-move让右移的数字也添加动画效果

vue为我们提供了默认的class叫.v-move{...}

敲代码

  // 相同代码已省略
  .v-move{
     transition: all 1s;
   }

运行结果

10.gif

状态动画

eg : 下面例子中数字1,变成数字10,不想让它一下及变成10。

而是有一个缓慢的过程,从1 -> 2 -> 3 -> 4 -> 5 -> 6 ... -> 10

敲代码

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

运行结果

11.gif

备注

状态动画就是通过控制数据来控制内容的展示,不断改变数据,达到的效果好像是一种动画的效果。状态动画不仅仅可以只做这些,当我们在做使用svg这种可以通过数据描述图片效果时,svg中的坐标可以通过变量去控制,就可以做些酷炫的动画