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 日期常用的方法
Nov 11 Javascript
Javascript对象属性方法汇总
Nov 21 Javascript
JavaScript避免代码的重复执行经验技巧分享
Apr 17 Javascript
js防止页面被iframe调用的方法
Oct 30 Javascript
js+html5实现可在手机上玩的拼图游戏
Jul 17 Javascript
js基于面向对象实现网页TAB选项卡菜单效果代码
Sep 09 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 Javascript
vue组件三大核心概念图文详解
May 30 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
Sep 02 Javascript
js全屏事件fullscreenchange 实现全屏、退出全屏操作
Sep 17 Javascript
jQuery Raty星级评分插件使用方法实例分析
Nov 25 jQuery
Node.js中出现未捕获异常的处理方法
Jun 29 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
JavaScript创建命名空间的5种写法
2014/06/24 PHP
php设计模式之单例模式代码
2016/06/11 PHP
cookie在javascript中的使用技巧以及隐私在服务器端的设置
2012/12/03 Javascript
jquery子元素过滤选择器使用示例
2013/06/24 Javascript
javascript实现避免页面按钮重复提交
2015/01/08 Javascript
Angular中的Promise对象($q介绍)
2015/03/03 Javascript
JavaScript实现横向滑出的多级菜单效果
2015/10/09 Javascript
JQuery+EasyUI轻松实现步骤条效果
2016/02/22 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
2016/09/04 Javascript
bootstrap网格系统使用方法解析
2017/01/13 Javascript
jquery图片放大镜效果
2017/06/23 jQuery
vue.js 实现输入框动态添加功能
2018/06/25 Javascript
vue中进入详情页记住滚动位置的方法(keep-alive)
2018/09/21 Javascript
node.js实现为PDF添加水印的示例代码
2018/12/05 Javascript
vue接口请求加密实例
2020/08/11 Javascript
[01:35]辉夜杯战队访谈宣传片—iG.V
2015/12/25 DOTA
[48:23]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#1COL VS EG第一局
2016/03/05 DOTA
[01:06:30]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第二场 1月9日
2021/03/11 DOTA
python网络编程之读取网站根目录实例
2014/09/30 Python
python求crc32值的方法
2014/10/05 Python
python版学生管理系统
2018/01/10 Python
Python拆分大型CSV文件代码实例
2019/10/07 Python
Django DRF路由与扩展功能的实现
2020/06/03 Python
Python urllib库如何添加headers过程解析
2020/10/05 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
学校门卫工作职责
2013/12/07 职场文书
元宵晚会主持词
2014/03/25 职场文书
小学生爱国演讲稿
2014/04/25 职场文书
含预算的公司户外活动方案
2014/08/16 职场文书
四风专项整治工作情况汇报
2014/10/28 职场文书
环保建议书作文500字
2015/09/14 职场文书
2019年行政人事个人工作总结范本!
2019/07/19 职场文书
SQL Server作业失败:无法确定所有者是否有服务器访问权限的解决方法
2021/06/30 SQL Server
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers