基于Vue过渡状态实例讲解


Posted in Javascript onSeptember 14, 2017

前面的话

Vue 的过渡系统提供了非常多简单的方法设置进入、离开和列表的动效。那么对于数据元素本身的动效呢?包括数字和运算、颜色的显示、SVG 节点的位置、元素的大小和其他的属性等。所有的原始数字都被事先存储起来,可以直接转换到数字。做到这一步,我们就可以结合 Vue 的响应式和组件系统,使用第三方库来实现切换元素的过渡状态

状态动画

通过watcher,能监听到任何数值属性的数值更新

<div id="animated-number-demo">
 <input v-model.number="number" type="number" step="20">
 <p>{{ animatedNumber }}</p>
</div>
<script src="Tween.js"></script>
<script src="vue.js"></script> 
<script>
new Vue({
 el: '#animated-number-demo',
 data: {
 number: 0,
 animatedNumber: 0
 },
 watch: {
 number: function(newValue, oldValue) {
  var vm = this;
  function animate () {
  if (TWEEN.update()) {
   requestAnimationFrame(animate)
  }
  }
  new TWEEN.Tween({ tweeningNumber: oldValue })
  .easing(TWEEN.Easing.Quadratic.Out)
  .to({ tweeningNumber: newValue }, 500)
  .onUpdate(function () {
   vm.animatedNumber = this.tweeningNumber.toFixed(0)
  })
  .start();
  animate()
 }
 }
}) 
</script>

当把数值更新时,就会触发动画。这个是一个不错的演示,但是对于不能直接像数字一样存储的值,比如 CSS 中的 color 的值,通过下面的例子来通过 Color.js 实现一个例子:

<div id="example">
 <input v-model="colorQuery" @keyup.enter="updateColor" placeholder="Enter a color">
 <button @click="updateColor">Update</button>
 <p>Preview:</p>
 <span :style="{ backgroundColor: tweenedCSSColor }" style="display: inline-block;width: 50px;height: 50px;"></span>
 <p>{{ tweenedCSSColor }}</p>
</div>
<script src="Tween.js"></script>
<script src="vue.js"></script> 
<script src="color.js"></script>
<script>
var Color = net.brehaut.Color
new Vue({
 el: '#example',
 data: {
 colorQuery: '',
 color: {
  red: 0,
  green: 0,
  blue: 0,
  alpha: 1
 },
 tweenedColor: {}
 },
 created: function () {
 this.tweenedColor = Object.assign({}, this.color)
 },
 watch: {
 color: function () {
  function animate () {
  if (TWEEN.update()) {
   requestAnimationFrame(animate)
  }
  }
  new TWEEN.Tween(this.tweenedColor)
  .to(this.color, 750)
  .start()
  animate()
 }
 },
 computed: {
 tweenedCSSColor: function () {
  return new Color({
  red: this.tweenedColor.red,
  green: this.tweenedColor.green,
  blue: this.tweenedColor.blue,
  alpha: this.tweenedColor.alpha
  }).toCSS()
 }
 },
 methods: {
 updateColor: function () {
  this.color = new Color(this.colorQuery).toRGB()
  this.colorQuery = ''
 }
 }
})
</script>

动态状态转换

就像 Vue 的过渡组件一样,数据背后状态转换会实时更新,这对于原型设计十分有用。当修改一些变量,即使是一个简单的 SVG 多边形也可以实现很多难以想象的效果

<style>
svg,input[type="range"]{display:block;} 
</style>
<div id="app">
 <svg width="200" height="200">
 <polygon :points="points" fill="#41B883"></polygon>
 <circle cx="100" cy="100" r="90" fill=" transparent" stroke="#35495E"></circle>
 </svg>
 <label>Sides: {{ sides }}</label>
 <input type="range" min="3" max="500" v-model.number="sides">
 <label>Minimum Radius: {{ minRadius }}%</label>
 <input type="range" min="0" max="90" v-model.number="minRadius">
 <label>Update Interval: {{ updateInterval }} milliseconds</label>
 <input type="range" min="10" max="2000" v-model.number="updateInterval">
</div>
 <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenLite.min.js"></script>
<script>
new Vue({
 el: '#app',
 data: function () {
 //默认有10条边
 var defaultSides = 10;
 //默认地,stats = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
 var stats = Array.apply(null, { length: defaultSides })
  .map(function () { return 100 })
 return {
  stats: stats,
  points: generatePoints(stats),
  sides: defaultSides,
  minRadius: 50,
  interval: null,
  updateInterval: 500
 }
 },
 watch: {
 sides: function (newSides, oldSides) {
  //计算设置的边数与默认的边数的差值
  var sidesDifference = newSides - oldSides
  //如果大于默认边数
  if (sidesDifference > 0) {
   //增加相应数量的随机值到stats数组中
   for (var i = 1; i <= sidesDifference; i++) {
    this.stats.push(this.newRandomValue())
   }
  }else{
   //否则,计算出差值
   var absoluteSidesDifference = Math.abs(sidesDifference)
   //从stats数组末尾减少相应数量的数组值
   for (var i = 1; i <= absoluteSidesDifference; i++) {
    this.stats.shift()
   }
  }
 },
 stats: function (newStats) {
  TweenLite.to(
   this.$data, 
   this.updateInterval / 1000, 
   { points: generatePoints(newStats) }
  )
 },
 updateInterval: function () {
  this.resetInterval()
 }
 },
 mounted: function () {
 this.resetInterval()
 },
 methods: {
 //将stats里面的值都变成50-100的随机值
 randomizeStats: function () {
  var vm = this
  this.stats = this.stats.map(function () {
  return vm.newRandomValue()
  })
 },
 newRandomValue: function () {
  //产生一个50-100的随机半径
  return Math.ceil(this.minRadius + Math.random() * (100 - this.minRadius))
 },
 //重启定时器
 resetInterval: function () {
  var vm = this;
  clearInterval(this.interval);
  this.randomizeStats();
  this.interval = setInterval(function () { 
   vm.randomizeStats();
  }, this.updateInterval)
 }
 }
})

function valueToPoint (value, index, total) {
 var x  = 0
 var y  = -value * 0.9
 var angle = Math.PI * 2 / total * index
 var cos = Math.cos(angle)
 var sin = Math.sin(angle)
 var tx = x * cos - y * sin + 100
 var ty = x * sin + y * cos + 100
 return { x: tx, y: ty }
}
//计算polygon中的路径点的值
function generatePoints (stats) {
 var total = stats.length
 return stats.map(function (stat, index) {
  var point = valueToPoint(stat, index, total)
  return point.x + ',' + point.y
 }).join(' ')
}
</script>

组件组织过渡

管理太多的状态转换会很快的增加 Vue 实例或者组件的复杂性,幸好很多的动画可以提取到专用的子组件

<div id="example">
 <input v-model.number="firstNumber" type="number" step="20"> +
 <input v-model.number="secondNumber" type="number" step="20"> =
 {{ result }}
 <p>
 <animated-integer :value="firstNumber"></animated-integer> +
 <animated-integer :value="secondNumber"></animated-integer> =
 <animated-integer :value="result"></animated-integer>
 </p>
</div>
<script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
<script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/Tween.js"></script>
<script>
Vue.component('animated-integer', {
 template: '<span>{{ tweeningValue }}</span>',
 props: {
 value: {
  type: Number,
  required: true
 }
 },
 data: function () {
 return {
  tweeningValue: 0
 }
 },
 watch: {
 value: function (newValue, oldValue) {
  this.tween(oldValue, newValue)
 }
 },
 mounted: function () {
 this.tween(0, this.value)
 },
 methods: {
 tween: function (startValue, endValue) {
  var vm = this;
  function animate () {
  if (TWEEN.update()) {
   requestAnimationFrame(animate)
  }
  }
  new TWEEN.Tween({ tweeningValue: startValue })
  .to({ tweeningValue: endValue }, 500)
  .onUpdate(function () {
   vm.tweeningValue = this.tweeningValue.toFixed(0)
  })
  .start()
  animate()
 }
 }
})
new Vue({
 el: '#example',
 data: {
 firstNumber: 20,
 secondNumber: 40
 },
 computed: {
 result: function () {
  return this.firstNumber + this.secondNumber
 }
 }
})
</script>

以上这篇基于Vue过渡状态实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js使用数组判断提交数据是否存在相同数据
Nov 27 Javascript
jquery性能优化高级技巧
Aug 24 Javascript
jqGrid中文文档之选项设置
Dec 02 Javascript
Bootstrap开关(switch)控件学习笔记分享
May 30 Javascript
详解JavaScript的内置对象
Dec 07 Javascript
jQuery多选框选择数量限制方法
Feb 08 Javascript
微信小程序开发之麦克风动画 帧动画 放大 淡出
Apr 18 Javascript
vue主动刷新页面及列表数据删除后的刷新实例
Sep 16 Javascript
深入理解与使用keep-alive(配合router-view缓存整个路由页面)
Sep 25 Javascript
vue+element 实现商城主题开发的示例代码
Mar 26 Javascript
vue实现在线学生录入系统
May 30 Javascript
React Ant Design树形表格的复杂增删改操作
Nov 02 Javascript
JavaScript使用atan2来绘制箭头和曲线的实例
Sep 14 #Javascript
Vue2.0基于vue-cli+webpack同级组件之间的通信教程(推荐)
Sep 14 #Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
Sep 14 #Javascript
对于js垃圾回收机制的理解
Sep 14 #Javascript
使用SVG基本操作API的实例讲解
Sep 14 #Javascript
JSON 数据格式详解
Sep 13 #Javascript
JS库 Highlightjs 添加代码行号的实现代码
Sep 13 #Javascript
You might like
2020年4月放送决定!第2期TV动画《邪神酱飞踢》视觉图&主题曲情报公开!
2020/03/06 日漫
2019年漫画销量排行榜:鬼灭登顶 海贼单卷制霸 尾田盛赞鬼灭
2020/03/08 日漫
解析file_get_contents模仿浏览器头(user_agent)获取数据
2013/06/27 PHP
php随机抽奖实例分析
2015/03/04 PHP
PHP实现简单实用的分页类代码
2016/04/08 PHP
PHP串行化与反串行化实例分析
2016/12/27 PHP
PHP开启目录引索+fancyindex漂亮目录浏览带搜索功能
2019/09/23 PHP
javascript实现表格排序 编辑 拖拽 缩放
2015/01/02 Javascript
js Calender控件使用详解
2015/01/05 Javascript
jQuery使用元素属性attr赋值详解
2015/02/27 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
JS中生成随机数的用法及相关函数
2016/01/09 Javascript
jquery实现页面常用的返回顶部效果
2016/03/04 Javascript
node+experss实现爬取电影天堂爬虫
2016/11/20 Javascript
JavaScript、C# URL编码、解码总结
2017/01/21 Javascript
jQuery实现一个简单的验证码功能
2017/06/26 jQuery
JavaScript中正则表达式判断匹配规则及常用方法
2017/08/03 Javascript
基于JS实现table导出Excel并保留样式
2020/05/19 Javascript
详解在IDEA中将Echarts引入web两种方式(使用js文件和maven的依赖导入)
2020/07/11 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
[02:05]2014DOTA2西雅图国际邀请赛 BBC第二天小组赛总结
2014/07/11 DOTA
python方法生成txt标签文件的实例代码
2018/05/10 Python
Django如何防止定时任务并发浅析
2019/05/14 Python
Python中Numpy mat的使用详解
2019/05/24 Python
Python3 全自动更新已安装的模块实现
2020/01/06 Python
Python语法垃圾回收机制原理解析
2020/03/25 Python
keras做CNN的训练误差loss的下降操作
2020/06/22 Python
一款简洁的纯css3代码实现的动画导航
2014/10/31 HTML / CSS
雅诗兰黛香港官网:Estee Lauder香港
2017/09/26 全球购物
优秀党员获奖感言
2014/02/18 职场文书
医院护士党的群众路线教育实践活动对照检查材料思想汇报
2014/10/04 职场文书
神农溪导游词
2015/02/11 职场文书
2015年安全生产月工作总结
2015/07/27 职场文书
信息技术远程培训心得体会
2016/01/09 职场文书
MySQL修炼之联结与集合浅析
2021/10/05 MySQL
在CSS中使用when/else的方法
2022/01/18 HTML / CSS