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 相关文章推荐
自动检查并替换文本框内的字符
Jun 30 Javascript
IE事件对象(The Internet Explorer Event Object)
Jun 27 Javascript
JavaScript的事件绑定(方便不支持js的时候)
Oct 01 Javascript
浅析Node.js查找字符串功能
Sep 03 Javascript
JavaScript实现找出数组中最长的连续数字序列
Sep 03 Javascript
jQuery实现响应鼠标滚动的动感菜单效果
Sep 21 Javascript
jQuery多文件异步上传带进度条实例代码
Aug 16 Javascript
微信小程序canvas写字板效果及实例
Jun 15 Javascript
基于Vue2.0+ElementUI实现表格翻页功能
Oct 23 Javascript
vue强制刷新组件的方法示例
Feb 28 Javascript
js验证账户名是否重复
May 26 Javascript
javascript实现放大镜功能
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
收藏的一个php小偷的核心程序
2007/04/09 PHP
小议Function.apply() 之一------(函数的劫持与对象的复制)
2006/11/30 Javascript
用于自动添加Digg This!按钮的JavaScript
2006/12/23 Javascript
javascript instanceof,typeof的区别
2010/03/24 Javascript
Dom 是什么的详细说明
2010/10/25 Javascript
js Map List 遍历使用示例
2013/07/10 Javascript
js去除空格的12种实用方法
2013/11/08 Javascript
js图片实时加载提供网页打开速度
2014/09/11 Javascript
在父页面得到zTree已选中的节点的方法
2015/02/12 Javascript
javascript面向对象程序设计高级特性经典教程(值得收藏)
2016/05/19 Javascript
微信小程序 wx.request(接口调用方式)详解及实例
2016/11/23 Javascript
jQuery实现最简单实用的分秒倒计时
2017/02/05 Javascript
vue.js加载新的内容(实例代码)
2017/06/01 Javascript
基于JQuery的Ajax方法使用详解
2017/08/16 jQuery
Nodejs实现文件上传的示例代码
2017/09/26 NodeJs
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
微信提示 在浏览器打开 效果实现过程解析
2019/09/10 Javascript
浅析JS中NEW的实现原理及重写
2020/02/20 Javascript
django简单的前后端分离的数据传输实例 axios
2020/05/18 Javascript
[50:50]完美世界DOTA2联赛PWL S3 Galaxy Racer vs Phoenix 第一场 12.10
2020/12/13 DOTA
Python的ORM框架SQLObject入门实例
2014/04/28 Python
python爬取亚马逊书籍信息代码分享
2017/12/09 Python
Python实现多条件筛选目标数据功能【测试可用】
2018/06/13 Python
win8下python3.4安装和环境配置图文教程
2018/07/31 Python
Python产生Gnuplot绘图数据的方法
2018/11/09 Python
Ubuntu下Anaconda和Pycharm配置方法详解
2019/06/14 Python
Django中使用haystack+whoosh实现搜索功能
2019/10/08 Python
Python 一行代码能实现丧心病狂的功能
2020/01/18 Python
浅谈tensorflow使用张量时的一些注意点tf.concat,tf.reshape,tf.stack
2020/06/23 Python
css3实现的多级渐变下拉菜单导航效果代码
2015/08/31 HTML / CSS
英国儿童图书网站:Scholastic
2017/03/26 全球购物
美国时尚假发购物网站:Wigsbuy
2019/04/06 全球购物
拓展策划方案
2014/06/03 职场文书
趣味运动会通讯稿
2015/07/18 职场文书
2016年学校“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书
MySQL优化常用的19种有效方法(推荐!)
2022/03/17 MySQL