anime.js 图片位移动画_「动画」想怎么动就怎么动,在我的地盘你得听我的

transition、animation是CSS3中制作DOM元素动画的重要属性,但其仅仅只能应对一些常规的需求,针对非DOM元素的属性过渡时就显得无能为力了,所以接下来通过js简单实现其动画原理(说白了也就是通过JavaScript间接操作目标过渡属性值,每隔一段时间更新一次)让动画变得更加灵活可控,而不是对可恶的pm说这效果有啥用、砍掉这类的话,当然还得看需求使用场景

aec73c0f759a5e945832295ed5cfdfac.png

先给个demo: 针对这样的需求怎么实现呢?

266702e0e94c0dc54e39c10cd004e030.gif

纯css显然已无法做到(图片有点失真,在线众筹换mac, 意思到位了就行~)

简单概述下上面的gif,布局采用了d3实现,针对这种需求常规的可视化图形插件(如ECharts、ichartjs等),通过简单的配置可能已无法做到,就算能实现灵活度也必然受到了限制。熟悉d3的同学实现起来也不会太复杂,图中主要是数字的变化以及弧形的颜色渐变的效果应如何实现,以及整体的联动。下面通过js来描述动画原理,使得更易于掌握css过渡transition及动画animation

关于transition和animation属性介绍有很多文章参考一篇CSS3的动画属性

接下来就使用js简单实现一个让div元素的width属性从20px过渡到200px的动画效果

html代码

css代码

#motionPath { width: 20px; height: 100px; color:#333; background-color: red;}

在实现之前,先简单了解下贝塞尔曲线的原理参考贝塞尔曲线扫盲,了解了原理之后推荐一个实现三次贝塞尔曲线的js库CubicBezier,也是下文中使用的动画函数,等价CSS transition-timing-function、animation-timing-function

首先定义过渡动画的几个参数:

  1. paused:控制动画暂停标志
  2. duration:动画过渡时间
  3. easing:动画过渡曲线,配置常规的动画过渡曲线参考缓动函数
  4. update:动画更新时的回调函数
var BezierEasing = require('bezier-easing')var tween = { paused: false, duration: 6000, easing: BezierEasing(0, 0, 1, 0.5), update: function (v) { // anim 是下文定义的一个描述动画的对象 anim.target.innerHTML = v }}

定义一个动画开始函数play()

var raf = nullfunction play() { raf = requestAnimationFrame(function (t) { step(t); }) function step(t) { if (!tween.paused) { setInstanceProgress(t); play(); } else { raf = cancelAnimationFrame(raf); } }}

step() 为动画的入口,这里使用requestAnimationFrame关键帧动画函数,当然也可用setTimeout来模拟实现,但更推荐使用requestAnimationFrame,推荐阅读深入理解requestAnimationFrame。在每一个动画关键帧周期内会调用setInstanceProgress() 函数,下面来看下setInstanceProgress() 函数的实现

function setInstanceProgress(engineTime) { var insTime = engineTime; if (insTime > tween.duration) { tween.paused = true; } var currentTime = Math.min(Math.max(insTime, 0), tween.duration);  setAnimationsProgress(currentTime);}

setInstanceProgress() 函数对动画时间进行了修正,同时会判断动画是否应该结束,并将修正的时间传给了setAnimationsProgress() 函数,同样再来看看setAnimationsProgress()函数的实现,我们知道动画其实是“位移”关于“时间”的函数:s=f(t)将动画函数与时间关联起来,计算 t 时刻动画属性值 f(t)

接下来再定义一个描述动画的对象 如下各参数的含义:

  1. target:过渡的目标对象,当前是div元素
  2. type:过渡的目标属性类型,元素的width归并于css
  3. property:目标过渡的属性名,也就是元素的宽width
  4. fromNumber:过渡的属性的起始值20px
  5. toNumber:过渡属性的结束值200px
var anim = { target: document.getElementById('motionPath'), type: 'css', property: 'width', fromNumber: 20, toNumber: 200}

setAnimationsProgress() 函数

function setAnimationsProgress(insTime) { var elapsed = insTime / tween.duration; var eased = tween.easing(elapsed); var value = anim.fromNumber + (eased * (anim.toNumber - anim.fromNumber)) setProgressValue[anim.type](anim.target, anim.property, value);  tween.update(value);}

setAnimationsProgress() 函数也就是动画的核心,把时间和过渡函数相结合,计算t时刻对应的value值,再把value值设置到过渡的目标对象属性中去,接下来就是setProgressValue的实现,针对DOM元素,设置width属性也就是设置style对应的属性

var setProgressValue = { css: function (t, p, v) { t.style[p] = v + 'px' }, plainkey: function (t, p, v) { t[p] = v }}

最后只需要运行play()函数,一个简单的动画也就实现了,效果如下:

70fe82e470367e3b552f4d29937b88f1.gif

如果说我们要过渡一个对象plain={key: 0}中的key属性值从 0 到 100 是不是修改一下anim参数就可以了,如下:

var plain = {key: 0}var anim = { target: plain, type: 'plainkey', property: 'key', fromNumber: 0, toNumber: 200}复制代码

key值的变化我就不给效果图了,总之通过这样简单的配置就解决了css不能实现类似的需求了,文章开头所说的数字变化的效果就完美的给解决了

最后一个问题了,文章开头的扇形的颜色渐变效果又应该如何实现呢,其实也很简单扇形是通过多份小扇形拼接而成的,然后设置相应的颜色,那每个小扇形应该设置什么样色来达到渐变的效果呢?

举例:从颜色#e8cf22 变化到 #48b532,应用上面所讲的过渡动画原理,#e8cf22对应的rgb格式为rgb(232, 207, 34),#48b532对应的rgb格式为rgb(72, 181, 50),那么分别对R、G、B各值按照对应的起始值和对应的终点值进行过渡(R:从232到72,G:从207到181,B:从34到50),过渡过程中再次组合对应的rgb值就是其过渡对应的颜色值,这就是颜色的过渡渐变原理,下面使用animejs这个库来实现,原理是一样的

html代码

css代码

#motionPath { color: blue; height: 100px;}

js代码

var oDev = document.getElementById('motionPath')anime({ targets: '#motionPath', duration: 6000, backgroundColor: ['rgb(232, 207, 34)', 'rgb(72, 181, 50)'] easing: 'easeInOutQuad', update: function (instance) { oDev.innerHTML = instance.animations[0].currentValue; }});

效果如下:

d33c474792906c4d0f4858f8092a3eae.gif

综上:了解了js如何实现动画之后,接下来看个使用css3 animation的例子,效果图就不粘出来了。 如下示例代码:

// div

最后

上文中的实现过程,读者你如果使用过animejs 这个动画函数库,也view过源代码,你会发现我只是参考其实现讲了一个大概,具体该函数库中一系列优秀的功能感兴趣的同学可以参考学习,非常值得推荐,目前GitHub上star已到达了30k+

在应对pm提出的一些需求中,只要清晰的知道要过渡那个具体属性,需要从某个起始状态变化到某个指定状态,然后以什么样的方式(过渡函数)来进行过渡,再结合过渡时间 duration,相信有这样的思路必然需求也会迎刃而解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值