土豆(tudou.com)首页的导航条,当鼠标移到到“社区”菜单时,对应的菜单的弹出效果比较有意思,类似于一个弹球落地的效果,对于有意思的东西,当然要研究研究。有兴趣的朋友可以自己先去看看效果,然后再来看文章。
tudou代码
看了tudou的js代码,发现他们也是使用jquery来实现动画效果的,代码如下:
f.style.height=0;
this.style.visibility="visible";
$(f).animate({height:g},500,"easeOutBounce");
$(i).addClass("hover")
最重要的是上面第三行代码,使用jquery的animate的函数,其中重点就是tudou自定义了animate的easing函数,即easeOutBounce函数,easeOutBounce函数如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | easeOutBounce: function (o,p,n,r,q){ if ((p/=q)<(1/2.75)){ return r*(7.5625*p*p)+n } else { if (p<(2/2.75)){ return r*(7.5625*(p-=(1.5/2.75))*p+0.75)+n } else { if (p<(2.5/2.75)){ return r*(7.5625*(p-=(2.25/2.75))*p+0.9375)+n } else { return r*(7.5625*(p-=(2.625/2.75))*p+0.984375)+n } } } } |
DEMO
先不分析代码,先用tudou的easeOutBounce函数做个demo看看效果。
demo(该demo在IE下点击没有效果,可能是跟博客园的其他代码有冲突,不想花时间去解决。要在IE下看效果,请copy后面的代码在本地进行测试):
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml"> < head > < meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> < script type="text/javascript" src="http://common.cnblogs.com/script/jquery.js"></ script > < script type="text/javascript"> jQuery.extend(jQuery.easing,{ def : "easeOutQuad", swing : function(o, p, n, r, q) { return jQuery.easing[jQuery.easing.def](o, p, n, r,q) }, easeOutBounce : function(o, p, n, r, q) { if ((p /= q) < (1 / 2.75)) { return r * (7.5625 * p * p) + n } else { if (p < (2 / 2.75)) { return r * (7.5625 * (p -= (1.5 / 2.75)) * p + 0.75) + n } else { if (p < (2.5 / 2.75)) { return r * (7.5625 * (p -= (2.25 / 2.75)) * p + 0.9375) + n } else { return r * (7.5625 * (p -= (2.625 / 2.75)) * p + 0.984375) + n } } } } }); function showMenu(){ resetMenu(); $("#b_menu").animate({height:100},500,"easeOutBounce"); } function resetMenu(){ $("#b_menu").show(); $("#b_menu").height(0); } </ script > < style type="text/css"> #b_menu{border:1px solid #F56E0B;width:100px;list-style:none;padding:0;height:0;overflow:hidden;display:none;} #b_menu li{line-height:25px;width:100px;text-align:center;} </ style > </ head > < body > < a href="javascript:showMenu();void(0)">我的菜单</ a >< br /> < ul id="b_menu"> < li >菜单一</ li > < li >菜单二</ li > < li >菜单三</ li > < li >菜单四</ li > </ ul > </ body > </ html > |
easing函数
jquery默认定义了2个easing函数,分别是swing和linear,easing函数格式如下:function(o, p, n, r, q)
但对于该几个参数的具体说明,jquery官方也没有文档说明(不知道是否是我没有找到),经过我看源代码和自己的理解,对几个参数理解如下:
o = p/q
p: 当前时间 - animate开始时间的毫秒值
n: 起始值,一直为0
r: 这个个人认为是递增值,一直为1
q: animate中的duration参数,即设置的动画效果运行完毕需要的时间
返回值:返回1个大于0,小于等于1的百分比值,animate方法通过这个百分比去计算各个参数的值
知道这几个参数的含义后,再看看tudou的easeOutBounce,就发现其第一行代码写的有问题,if ((p /= q) < (1 / 2.75)) 其实可以直接写成 if ((o) < (1 / 2.75)) 。
可以看出tudou的开发人员对easing函数的几个参数也不太理解,不然就不会这样写了(也有可能easeOutBounce函数,tudou也是直接从其他地方copy过来的,呵呵)
胡言乱语
在查询jquery的easing参数的时候,无意间发现1个专门做easing效果的网站(http://gsgd.co.uk/sandbox/jquery/easing/),而土豆的几个easing效果代码跟该网站的easing效果代码是惊人的相似,除了参数名不同外(这也出现我前面copy 代码的猜测),其实是不是copy都无所谓的,偶也是胡言乱语下,大家也别想太多,贴出2段代码,大家自己看看吧。
下面tudou的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | jQuery.extend(jQuery.easing,{ def : "easeOutQuad" , swing : function (o, p, n, r, q) { return jQuery.easing[jQuery.easing.def](o, p, n, r,q) }, easeInQuad : function (o, p, n, r, q) { return r * (p /= q) * p + n }, easeOutQuad : function (o, p, n, r, q) { return -r * (p /= q) * (p - 2) + n }, easeInOutQuad : function (o, p, n, r, q) { if ((p /= q / 2) < 1) { return r / 2 * p * p * p + n } return r / 2 * ((p -= 2) * p * p + 2) + n }, easeInBack : function (o, p, n, u, r, q) { if (q == undefined) { q = 1.70158 } return u * (p /= r) * p * ((q + 1) * p - q) + n }, easeOutBack : function (o, p, n, u, r, q) { if (q == undefined) { q = 1.70158 } return u * ((p = p / r - 1) * p * ((q + 1) * p + q) + 1) + n }, easeOutBounce : function (o, p, n, r, q) { if ((p /= q) < (1 / 2.75)) { return r * (7.5625 * p * p) + n } else { if (p < (2 / 2.75)) { return r * (7.5625 * (p -= (1.5 / 2.75)) * p + 0.75) + n } else { if (p < (2.5 / 2.75)) { return r * (7.5625 * (p -= (2.25 / 2.75)) * p + 0.9375) + n } else { return r * (7.5625 * (p -= (2.625 / 2.75)) * p + 0.984375) + n } } } } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | jQuery.extend( jQuery.easing,{ def: 'easeOutQuad' , swing: function (x, t, b, c, d) { //alert(jQuery.easing.default); return jQuery.easing[jQuery.easing.def](x, t, b, c, d); }, easeInQuad: function (x, t, b, c, d) { return c*(t/=d)*t + b; }, easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, easeInOutQuad: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }, easeInCubic: function (x, t, b, c, d) { return c*(t/=d)*t*t + b; }, easeOutCubic: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }, easeInOutCubic: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t + b; return c/2*((t-=2)*t*t + 2) + b; }, easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }, easeOutQuart: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }, easeInOutQuart: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 * ((t-=2)*t*t*t - 2) + b; }, easeInQuint: function (x, t, b, c, d) { return c*(t/=d)*t*t*t*t + b; }, easeOutQuint: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t*t*t + 1) + b; }, easeInOutQuint: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }, easeInSine: function (x, t, b, c, d) { return -c * Math.cos(t/d * (Math.PI/2)) + c + b; }, easeOutSine: function (x, t, b, c, d) { return c * Math.sin(t/d * (Math.PI/2)) + b; }, easeInOutSine: function (x, t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }, easeInExpo: function (x, t, b, c, d) { return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; }, easeOutExpo: function (x, t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; }, easeInOutExpo: function (x, t, b, c, d) { if (t==0) return b; if (t==d) return b+c; if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; }, easeInCirc: function (x, t, b, c, d) { return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; }, easeOutCirc: function (x, t, b, c, d) { return c * Math.sqrt(1 - (t=t/d-1)*t) + b; }, easeInOutCirc: function (x, t, b, c, d) { if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; }, easeInElastic: function (x, t, b, c, d) { var s=1.70158; var p=0; var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, easeOutElastic: function (x, t, b, c, d) { var s=1.70158; var p=0; var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, easeInOutElastic: function (x, t, b, c, d) { var s=1.70158; var p=0; var a=c; if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, easeInBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, easeInOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, easeInBounce: function (x, t, b, c, d) { return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; }, easeOutBounce: function (x, t, b, c, d) { if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, easeInOutBounce: function (x, t, b, c, d) { if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; } }); |
相关链接
分类:
名站技术分析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)