jquery animate扩展

博客探讨如何扩展jQuery的animate函数,以实现非CSS属性的动画效果,如数值变化。作者提出,真正的核心是获取每一帧的进度信息,让业务层根据进度处理变化。文章通过示例解释了如何创建一个接受初始值、最终值、时间和回调函数的animate方法,以支持多个数据同步变化,并讨论了如何优化性能以适应浏览器渲染。
摘要由CSDN通过智能技术生成

jquery animate函数是作用在css属性上的,但有些时候我们的动画不是作用在css属性之上,还是老问题在3s内,将一个div上显示的数字从0变到100.

在上一篇博客 jquery animate妙用 中我们曾探讨过这个问题,也找到了一个巧妙地方法,现在的话,忘了之前你看到的吧,我们从另一个角度来思考一下这个问题。

jquery的animate已经实现了css属性动画,我们没必要去重复发明轮子,我们需要的是来弥补jquery的不足:实现一个值动画的animate。那什么是值动画呢?通常我们要实现一个动画,思路一般就是将其先分解为多少帧,然后每一帧去改变它的状态,如果我们只是想让一个数据在某一段时间从x变到y,而在这个过程中我们需要使用这个不断变化的值去做一些事,可能不是去更新ui,但也可能事,我们就姑且称之为动画吧,因为动画一般是指ui在一段时间发生连续性的变化,而我们的是数据。举个栗子,正如我之前提到的老问题:3s内,将一个div上显示的数字从0变到100(这个栗子太好了,哪里都能用,皮黄心白,口味甘甜,实在是居家旅行,出门必备品)。那么我们希望的animate是这样的:

animate(0,100,3000, function (val){
  div.text(a)
})

四个参数一次是初始值 最终值 动画时间  和每一帧的回调(val范围是[0,100]) ,是不是很清晰? 这就打完收工了? no !  如果我的要求变一下,在3s内,将一个div上显示的数字从0变到100,同时将它的left值从0变到785.  这怎么办? 写上两个animate? 显然不好,也许改成这样你会欢喜:

animate({text:100,left:785},3000, function (o){
  div.text(o.text).css( "left" :o.left)
})

这样好像很棒,支持多个数据变化,看看这是不是似曾相识的感觉?这和jquery的animate太像了,其实jquery的animate是可以实现这样的功能的,详情请移步 jquery animate妙用

如果问题现在再变一下,要求在3s内,将一个div上显示的数字从快到慢地(匀减速)从0变到100,同时将它的left值从0变到785.  这怎么办?  这样我们就需要一个进度信息,然后就知道在时间轴上动画已经走了多长时间,这样就可以抽象出一个t,然后通过自己指定的加速度去控制,当然,我们可以在回掉中传入第二个参数t。不过现在,我们并不打算这么做,好了,我们回过偷来好好想一下,其实无论对于什么动画,无论是属性动画还是数据动画,业务最关心的是每一帧动画的进度,一旦有了这个进度信息,我们就知道该怎么做了,所以,我们完全可以不关心到底有什么数据从什么样的范围变化,这是业务层关心的,animate只关心动画的进度,比如1/10,1/5, 用户根据这个进度决定自己的操作,比如最初的老问题可以这么解决:

animate(3000, function (time){
  var  progress=time/3000;
  div.text(100*progress).css( "left" ,785*progress)
})

animate本身根本不需要知道有哪些数据变化,以及他们的变化范围,它只提供一个进度(time表示当前动画已经走了多久了),而用户根据自己的业务去做处理就行!

这样是最合理的,就是可能用户在执行回调用的时候需要依赖/修改/保存一些数据以供下一帧使用,我们可以提供一种重载,添加一个可选的参数arguments, 然后在每一帧执行回调时传递给回调函数,下面看源码吧:

$.animate= function  (speed,arguments,callback){
     if (speed<30) speed=30;
        //可能调用时用户没有传arguments
     var  f=callback||arguments
     var  argvs=callback&&(arguments.speed=speed)&&arguments;
     var  frameCount=Math.ceil(speed/1000)*30
     var  t=speed/frameCount;
     var  ct=0,timer;
     function  proxy(){
         ct+=t;
         if (ct>speed) {clearInterval(timer); f(speed,argvs);  return ;}
         f(ct,argvs);
     }
     timer=setInterval(proxy,t)
}


需要说明的是,我们是固定1s钟分30帧,而为了更合理的利用浏览器渲染,提高性能,我们通过requestAnimationFrame和cancelAnimationFrame来替换直接将帧数写死,不认识这两个面孔的请直接百度吧。下面试最终实现:

window.requestAnimationFrame =requestAnimationFrame|| function (callback){setTimeout(callback, 1000/60)}
window.cancelAnimationFrame =cancelAnimationFrame|| function (id) {clearTimeout(id)}
$.animate1= function  (speed,arguments,callback){
     if (speed<30) speed=30;
     var  f=callback||arguments
     var  argvs=callback&&(arguments.speed=speed)&&arguments;
     function  proxy(c){
         if (c>speed) { f(speed,argvs);  return ;}
         f(c,argvs);
         requestAnimationFrame(proxy);
      }
      requestAnimationFrame(proxy)
}

animate就讨论到这里,下次有时间我把自己实现的旋转插件和附带的一些示例再分享,这些代码中都用到了现在以及之前讨论的一些东西。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值