您的位置:知识库 » Web前端

名站技术分析 — tudou网首页下列菜单的弹出效果

作者: BearRui(AK-47)  来源: 博客园  发布时间: 2010-11-08 21:32  阅读: 976 次  推荐: 0   原文链接   [收藏]  
摘要:土豆(tudou.com)首页的导航条,当鼠标移到到“社区”菜单时,对应的菜单的弹出效果比较有意思,类似于一个弹球落地的效果,对于有意思的东西,当然要研究研究。

  土豆(tudou.com)首页的导航条,当鼠标移到到“社区”菜单时,对应的菜单的弹出效果比较有意思,类似于一个弹球落地的效果,对于有意思的东西,当然要研究研究。有兴趣的朋友可以自己先去看看效果,然后再来看文章。

  tudou代码

  看了tudou的js代码,发现他们也是使用jquery来实现动画效果的,代码如下:

1
2
3
4
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">
    <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
                }
            }
        }
    }
});
http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js 代码
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;
    }
});
0
0

Web前端热门文章

    Web前端最新文章

      最新新闻

        热门新闻