视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
vue2.0 中使用transition实现动画效果使用心得
2020-11-27 22:10:00 责编:小采
文档


实践

这里将通过四个实践小案例来体验和学习css过渡,css动画,javascript钩子,列表过渡的应用。至于案例用到的知识点就请自行学习官网文档。

1.css过渡–实践

先来看看demo效果:

这个案例其实很简单,通过一个transition来触发多个子元素的过渡效果,我们只需要定义元素对应的过渡效果就可以,其他事情vue会帮我们搞定,由此可以扩展出其他酷炫的过渡场景效果。先来看看这个简单案例的代码实现:

<template>
 <div class="app">
 <button @click="showMenu" class="btn">{{text}}</button>
 <transition name="move">
 <div class="menu" v-show="show">
 <div class="inner inner-1">1</div>
 <div class="inner inner-2">2</div>
 <div class="inner inner-3">3</div>
 </div>
 </transition>
 </div>
</template>

<script type="text/ecmascript-6">
 export default {
 data () {
 return {
 show: false
 };
 },
 methods: {
 showMenu () {
 this.show = !this.show;
 }
 },
 computed: {
 text () {
 return this.show ? '收' : '开';
 }
 }
 };
</script>

<style lang="stylus" rel="stylesheet/stylus">
 .app
 .btn
 position: fixed
 bottom: 50px
 right: 10px
 z-index: 10
 width: 50px
 height: 50px
 line-height: 50px
 border-radius: 50%
 border: none
 outline: none
 color: #fff
 font-size: 18px
 background: blue
 .menu
 position: fixed
 bottom: 50px
 right: 10px
 width: 50px
 height: 50px
 border-radius: 50%
 transition: all .7s ease-in
 &.move-enter-active
 .inner
 transform: translate3d(0, 0, 0)
 transition-timing-function: cubic-bezier(0, .57, .44, 1.97)
 .inner-1
 transition-delay: .1s
 .inner-2
 transition-delay: .2s
 .inner-3
 transition-delay: .3s
 &.move-enter, &.move-leave-active
 .inner
 transition-timing-function: ease-in-out
 .inner-1
 transform: translate3d(0, 60px, 0)
 transition-delay: .3s
 .inner-2
 transform: translate3d(40px, 40px, 0)
 transition-delay: .2s
 .inner-3
 transform: translate3d(60px, 0, 0)
 transition-delay: .1s
 .inner
 display: inline-block
 position: absolute
 width: 30px
 height: 30px
 line-height: 30px
 border-radius: 50%
 background: red
 text-align: center
 color: #fff
 transition: all .4s
 .inner-1
 top: -50px
 left: 10px
 .inner-2
 left: -30px
 top: -30px
 .inner-3
 left: -50px
 top: 10px
</style>

可以看到我们的代码基本主要是完成css过渡效果的样式,而触发过渡效果只是简单地通过一个click事件就搞定了,vue会自动嗅探目标元素是否有 CSS 过渡或动画,并在合适时添加/删除 CSS 类名。那下一个demo就来简单实现一下使用css animation 做过渡的效果。

2.css 动画–实践

先来看看demo效果:

这个案例其实跟上面的demo差不多,不同之处在于过渡效果是使用css动画来实现,看下实现的代码:

<template>
 <div class="app">
 <button @click="showball" class="btn">show</button>
 <transition name="move" type="animation">
 <div class="ball" v-show="show">
 <div class="inner"></div>
 </div>
 </transition>
 </div>
</template>

<script type="text/ecmascript-6">
 export default {
 data () {
 return {
 show: false
 };
 },
 methods: {
 showball () {
 this.show = !this.show;
 }
 }
 };
</script>

<style lang="stylus" rel="stylesheet/stylus">
 @keyframes shape-change {
 0%, 100% {
 border-radius: 50%
 background: red
 }
 50% {
 border-radius: 0
 background: blue
 }
 }

 @keyframes moveball-in {
 0% {
 transform: translate3d(300px,-200px,0)
 }
 50% {
 transform: translate3d(100px,-400px,0)
 }
 100% {
 transform: translate3d(0,0,0)
 }
 }
 @keyframes moveball-out {
 0% {
 transform: translate3d(0,0,0)
 }
 50% {
 transform: translate3d(100px,-400px,0)
 }
 100% {
 transform: translate3d(300px,-200px,0)
 }
 }
 .app
 .btn
 width: 40px
 height: 30px
 margin-top: 40px
 border: none
 outline: none
 background: red
 color: #fff
 .ball
 position: absolute
 bottom: 20px
 left: 20px
 width: 50px
 height: 50px
 transition: all 1s cubic-bezier(.22,-0.86,.97,.58)
 &.move-enter-active
 opacity: 1
 animation: moveball-in 1s
 .inner
 animation: shape-change 1s
 &.move-leave-active
 opacity: 0.8
 animation: moveball-out 1s
 .inner
 animation: shape-change 1s
 .inner
 display: inline-block
 width: 30px
 height: 30px
 border-radius: 50%
 background: red
 transition: all 1s linear
</style>

从css代码可以看出,我们只是在vue过渡类名下加了不同的animation而已。官网文档明确说明当只使用transition或animation其中一种时,vue是能自动监听对应的类型的,但是如果同一个元素同时使用两种效果,就需要明确指定监听哪一种类型,不过官网并没有给出具体的栗子。那其实这个demo已经简单地实现同时使用两种类型的情况,可以看到有一个透明度的变化。但是假如animation里使用了transform,并且外面也使用了transform的话,那么元素在过渡的时候动画效果就会有冲突,效果就有点出入了。

3.JavaScript钩子 – 实践

前两个栗子都是有进入和离开的过渡,但是如果一些场景只需要进入过渡然后就结束了,那么这时就可以使用JavaScript钩子结合CSS transitions/animations来实现,当然也可以单独使用。看下demo:

这个一个非常low的模拟炮弹发射的场景,可以看到小球有抛物线轨迹运动的过渡,而且发射出去就不会再回来了,那么这个demo就是使用了JavaScript钩子结合css来实现的,接下来看下关键代码:

<template>
 <div class="app">
 <div class="gun" @click="launch($event)"></div>
 <div class="shells-wrapper">
 <transition v-for="shell in shells" name="launch-shell" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
 <div class="shell" v-show="shell.show">
 <div class="inner"></div>
 </div>
 </transition>
 </div>
 <div class="goal"></div>


 <!--小球第二种-->
 <div class="ball-container">
 <ul>
 <li v-for="(ball,index) in balls" :key="index">
 <transition :css="false" name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
 <div class="ball" v-show="ball.show">
 <div class="inner inner-hook"></div>
 </div>
 </transition>
 </li>
 </ul>
 </div>
 <!--小球 End-->
 </div>
</template>

首先,由于本身这个demo是一组元素的过渡,所以有些童鞋就会觉得用2.0提供的transition-group不就行了嘛。不过transition-group是列表过渡,我的理解是那一组元素是相关联的、互相影响的,但是这个demo的元素每个都是的,只不过是一组的元素过渡,所以还是用transition比较合理,那使用v-for就可以实现一组相同过渡的元素啦。接下来看JavaScript钩子怎么实现这个过渡:

export default {
 data () {
 return {
 shells: [
 {
 show: false
 },
 {
 show: false
 },
 {
 show: false
 }
 ]
 };
 },
 methods: {
 launch (event) {
 for (let i = 0; i < this.shells.length; i++) {
 let shell = this.shells[i];
 if (!shell.show) {
 shell.show = true;
 shell.target = event.target;
 return;
 }
 }
 },
 beforeEnter (el) {
 let count = this.shells.length;
 while (count--) {
 let shell = this.shells[count];
 if (shell.show) {
 let rect = shell.target.getBoundingClientRect();
 let left = rect.left - 32;
 let top = -(window.innerHeight - rect.top - 15);
 el.style.display = '';
 el.style.webkitTransform = `translate3d(0,${top}px,0)`;
 el.style.transform = `translate3d(0,${top}px,0)`;
 let inner = el.getElementsByClassName('inner')[0];
 inner.style.webkitTransform = `translate3d(${left}px,0,0)`;
 inner.style.transform = `translate3d(${left}px,0,0)`;
 }
 }
 },
 enter (el, done) {
 /* eslint-disable no-unused-vars */
 let refresh = el.offsetHeight;
 this.$nextTick(() => {
 el.style.webkitTransform = 'translate3d(0,0,0)';
 el.style.transform = 'translate3d(0,0,0)';
 let inner = el.getElementsByClassName('inner')[0];
 inner.style.webkitTransform = 'translate3d(0,0,0)';
 inner.style.transform = 'translate3d(0,0,0)';
 });
 done();
 },
 afterEnter (el) {
 let ball = this.shells[0];
 ball.show = false;
 el.style.display = 'none';
 }
 }
 };

css样式代码:

.ball-container
 .ball
 position: absolute
 left: 32px
 bottom: 22px
 z-index: 50
 transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
 .inner
 width: 16px
 height: 16px
 border-radius: 50%
 background: rgb(0, 160, 220)
 transition: all 0.4s linear

过渡元素就不需要为其添加vue的过渡css类名了,只需在元素本身添加transition即可,那vue在之前css过渡的时候会自动帮我们去添加对应的类名来完成过渡效果,但是用javascript钩子就需要我们自己完成这个始末状态的设置了。当我们点击触发一个过渡的时候,我们在beforeEnter里先拿到当前元素的偏移位置,然后给过渡元素设置其起始位置,在enter里需要重新触发下浏览器的重绘,然后在下一帧重新设置元素的结束位置,这时就会产生过渡效果,在过渡完成后我们将当前元素隐藏即可。那刚才讲到的列表过渡,接下来就是关于使用transition-group的一个小demo了。

4.transition-group – 实践

先看下demo效果:

其实就是个简单的todo lists的小demo,可以看到,当其中一个元素过渡的时候,会影响其他元素的过渡。当然,删除按钮其实本身也是一个transition过渡,也就是说可以在transition-group里使用transition,看下相关代码:

<template>
 <div class="app">
 <button @click="add" class="add-btn">+</button>
 <transition-group name="slide" tag="ul" class="list-wrapper">
 <li class="list" v-for="(item, index) in lists" v-touch:swipeleft="showBtn.bind(this, index)" v-touch:swiperight="hideBtn.bind(this, index)" :key="item">
 <span class="text">{{item.text}}</span>
 <transition name="move">
 <button class="del-btn" @click="delList(index)" v-show="item.show">删除</button>
 </transition>
 </li>
 </transition-group>
 </div>
</template>

有个小坑的地方就是,之前看官网列表过渡的栗子,它是一个数组,元素都是数字,并且每一项都必须设置唯一的key值。所以我完成demo的时候就自作聪明地将索引值传给key,结果过渡老是不对,后来换成对应的item就正常了(生无可恋脸)。这个demo用到了vue-touch,虽然github上说不支持2.0版本了,但是有一个next分支是支持的,只需在项目下安装它即可:

sudo npm install --save git: //github.com/vuejs/vue-touch.git#next

这里看下主要的样式:

.list
 display: flex
 width: 100%
 height: 40px
 line-height: 40px
 margin-bottom: 10px
 color: #666
 font-size: 14px
 background: #eee
 transition: all .4s
 &.slide-move
 transition: transform 1s
 &.slide-enter
 transform: translate3d(-100%, 0, 0)
 &.slide-leave-active
 position: absolute
 transform: translate3d(-100%, 0, 0)
 &:last-child
 margin-bottom: 0
 .del-btn
 flex: 0 0 60px
 border: none
 outline: none
 color: #fff
 background: red
 transition: all .4s
 &.move-enter, &.move-leave-active
 transform: translate3d(70px, 0, 0)
 .text
 flex: 1
 padding-left: 20px

如果改变定位过渡的duration与进入离开一样的话,其实可以不用-move,这里设置-move的过渡的duration不同于元素进入离开的duration产生一种速度差,看起来舒服点。而且-leave-active需要设置position: absolute才会有效果。现在看来其实列表过渡也是很容易实现的。

ps:下面看下vue.js 2.* 使用transition实现动画效果

<transition name="fade">
 <div class="detail" v-show="detailShow"></div>
</transition>
<script type="text/ecmascript-6">
 export default {
 };
</script>
<style lang="stylus" ref="sheetstyle/stylus">
 .fade-enter-active, .fade-leave-active 
 opacity:1
 transition: all 1.0s 
 background:rgba(7,17,27,0.8) 
 .fade-enter, .fade-leave-active 
 opacity: 0
 background:rgba(7,17,27,0)
</style>

总结

以上所述是小编给大家介绍的vue2.0 中使用transition实现动画效果使用心得,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

下载本文
显示全文
专题