vue2.0 中使用transition实现动画效果使用心得


Posted in Javascript onAugust 13, 2018

实践

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

1.css过渡?实践

先来看看demo效果:

vue2.0 中使用transition实现动画效果使用心得

这个案例其实很简单,通过一个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效果:

vue2.0 中使用transition实现动画效果使用心得

这个案例其实跟上面的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:

vue2.0 中使用transition实现动画效果使用心得

这个一个非常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效果:

vue2.0 中使用transition实现动画效果使用心得

其实就是个简单的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实现动画效果使用心得,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 建设银行登陆键盘
Jun 10 Javascript
Jvascript学习实践案例(开发常用)
Jun 25 Javascript
关于javascript event flow 的一个bug详解
Sep 17 Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
Feb 11 Javascript
jQuery表格插件datatables用法详解
Nov 23 Javascript
Vue组件模板形式实现对象数组数据循环为树形结构(实例代码)
Jul 31 Javascript
浅谈angular2路由预加载策略
Oct 04 Javascript
element-ui 表格数据时间格式化的方法
Aug 24 Javascript
详解webpack之图片引入-增强的file-loader:url-loader
Oct 08 Javascript
vue中keep-alive、activated的探讨和使用详解
Jul 26 Javascript
nuxt引入组件和公共样式的操作
Nov 05 Javascript
手把手教你如何编译打包video.js
Dec 09 Javascript
vue.js2.0 实现better-scroll的滚动效果实例详解
Aug 13 #Javascript
jQuery实现图片简单轮播功能示例
Aug 13 #jQuery
vue.js 实现评价五角星组件的实例代码
Aug 13 #Javascript
Vue.js实现数据响应的方法
Aug 13 #Javascript
jQuery模拟12306城市选择框功能简单实现方法示例
Aug 13 #jQuery
Bootstrap Table实现定时刷新数据的方法
Aug 13 #Javascript
angular2实现统一的http请求头方法
Aug 13 #Javascript
You might like
微信支付开发动态链接Native支付
2016/07/12 PHP
PHP精确到毫秒秒杀倒计时实例详解
2019/03/14 PHP
Laravel 模型关联基础教程详解
2019/09/17 PHP
laravel框架如何设置公共头和公共尾
2019/10/22 PHP
jquery 单引号和双引号的区别及使用注意
2013/07/31 Javascript
js触发onchange事件的方法说明
2014/03/08 Javascript
javascript:void(0)的问题使用探讨
2014/04/10 Javascript
JavaScript获取当前网页最后修改时间的方法
2015/04/03 Javascript
js实现简单div拖拽功能实例
2015/05/12 Javascript
原生js实现模拟滚动条
2015/06/15 Javascript
跟我学习javascript的prototype原型和原型链
2015/11/18 Javascript
JQuery.Ajax()的data参数类型实例详解
2015/11/20 Javascript
JavaScript实现给定时间相加天数的方法
2016/01/25 Javascript
jquery div模态窗口的简单实例
2016/05/28 Javascript
JS中正则表达式只有3种匹配模式(没有单行模式)详解
2016/07/28 Javascript
jQuery实现的简单在线计算器功能
2017/05/11 jQuery
jQuery回调方法使用示例
2017/06/26 jQuery
jQuery实现动态控制页面元素的方法分析
2017/12/20 jQuery
JavaScript运行原理分析
2018/02/09 Javascript
详解如何使用koa实现socket.io官网的例子
2018/11/04 Javascript
python计算对角线有理函数插值的方法
2015/05/07 Python
Python采用Django开发自己的博客系统
2020/09/29 Python
启动Atom并运行python文件的步骤
2018/11/09 Python
python操作excel让工作自动化
2019/08/09 Python
基于django ManyToMany 使用的注意事项详解
2019/08/09 Python
python实现的Iou与Giou代码
2020/01/18 Python
Python3 集合set入门基础
2020/02/10 Python
CSS3实现复选框动画特效示例代码
2016/09/27 HTML / CSS
极简的HTML5模版
2015/07/09 HTML / CSS
澳大利亚的奢侈品牌:Oroton
2016/08/26 全球购物
瑞典首都斯德哥尔摩的多元奢侈时尚品牌:Acne Studios
2017/07/09 全球购物
建筑工程技术应届生求职信
2013/11/17 职场文书
青年志愿者先进事迹
2014/05/06 职场文书
品酒会策划方案
2014/05/26 职场文书
四风剖析查摆对照检查材料思想汇报
2014/09/24 职场文书
六五普法心得体会2016
2016/01/21 职场文书