jQuery插件stickup.js 源码解析初步

 

这里只是一个初步的解析

 

stickup.js是一个简单的jQuery插件,源代码只有100多行,它能让页面目标元素 “固定” 在浏览器窗口的顶部,即便页面在滚动,目标元素仍然能出现在设定的位置。

介绍:http://www.bootcss.com/p/stickup/

源码地址:https://github.com/LiranCohen/stickUp

 

同时,还有一个改进版本可以参考:http://www.cnblogs.com/vans/p/3789416.html

源码地址:https://github.com/VanMess/stickUp

  1 jQuery(function($) {
  2     
  3     $(document).ready(function(){
  4         var contentButton = [];
  5         var contentTop = [];
  6         var content = [];
  7         var lastScrollTop = 0;
  8         var scrollDir = '';
  9         var itemClass = '';
 10         var itemHover = '';
 11         var menuSize = null;
 12         var stickyHeight = 0;
 13         var stickyMarginB = 0;
 14         var currentMarginT = 0;
 15         var topMargin = 0;
 16 
 17 
 18         $(window).scroll(function(event){
 19                var st = $(this).scrollTop();
 20                if (st > lastScrollTop){
 21                    scrollDir = 'down';
 22                } else {
 23                   scrollDir = 'up';
 24                }
 25               lastScrollTop = st;
 26         });
 27 
 28         /***********************************************************/
 29         $.fn.stickUp = function( options ) {
 30             // adding a class to users div
 31             $(this).addClass('stuckMenu');
 32             //getting options
 33             var objn = 0;    //objn表示导航条对象有n个
 34             if(options != null) {
 35                 for(var o in options.parts) {    //option.parts指导航条对象
 36                     if (options.parts.hasOwnProperty(o)){
 37                         content[objn] = options.parts[objn];    //content对象是options.parts的深拷贝
 38                         objn++;
 39                     }
 40                 }
 41                   if(objn == 0) {
 42                       console.log('error:needs arguments');
 43                   }
 44 
 45                   itemClass = options.itemClass;
 46                   itemHover = options.itemHover;
 47 
 48                   itemTop = options.topLength;    //新添加
 49 
 50                   if(options.topMargin != null) {
 51                       if(options.topMargin == 'auto') {
 52                           topMargin = parseInt($('.stuckMenu').css('margin-top'));
 53                       } else {
 54                           //如果以px结尾的topMargin,如options.topMargin:10px,则topMargin=10    此处是否有bug,如 abcpx
 55                           if(isNaN(options.topMargin) && options.topMargin.search("px") > 0){
 56                               topMargin = parseInt(options.topMargin.replace("px",""));
 57                           //如果topMargin是数字,如options.topMargin:10,则topMargin=10                          
 58                           } else if(!isNaN(parseInt(options.topMargin))) {
 59                               topMargin = parseInt(options.topMargin);
 60                           } else {
 61                               //既不是数字,也不是以px结尾,也不是auto,那么就默认为0
 62                               console.log("incorrect argument, ignored.");
 63                               topMargin = 0;
 64                           }    
 65                       }
 66                   } else {
 67                       topMargin = 0;
 68                   }
 69                   menuSize = $('.'+itemClass).size();    //menuSize指jQuery选择器匹配的元素的数量
 70               }
 71             stickyHeight = parseInt($(this).height());
 72             stickyMarginB = parseInt($(this).css('margin-bottom'));
 73             currentMarginT = parseInt($(this).next().closest('div').css('margin-top'));
 74             vartop = parseInt($(this).offset().top);
 75 
 76             varleft = parseInt($(this).offset().left);    //新添加
 77             varParentWidth = parseInt($(this).parent().offset().width());    //新添加:计算菜单栏悬浮时的宽度
 78             varParentLeft = parseInt($(this).parent().offset().left);    //新添加:计算菜单栏悬浮时的距离在屏幕左边的宽度
 79 
 80             //$(this).find('*').removeClass(itemHover);
 81         }
 82 
 83         //document对象绑定滚动事件,通过监听滚轮位置来识别内容位置,给导航栏切换对应样式
 84         $(document).on('scroll', function() {
 85             //scrollTop()方法返回或设置匹配元素的滚动条的垂直位置。
 86             //如果该方法未设置参数,则返回以像素计的相对滚动条顶部的偏移。
 87             varscroll = parseInt($(document).scrollTop());    
 88 
 89             if(menuSize != null){
 90                 for(var i=0;i < menuSize;i++)
 91                 {
 92                     contentTop[i] = $('#'+content[i]+'').offset().top;    //当前内容位置的偏移(第一个元素匹配的偏移坐标)
 93                     function bottomView(i) {
 94                         contentView = $('#'+content[i]+'').height()*.4;    //当前内容区域高度的 0.4
 95                         testView = contentTop[i] - contentView;    //当前内容区域往上
 96                         //console.log(varscroll);
 97                         if(varscroll > testView){
 98                             $('.'+itemClass).removeClass(itemHover);
 99                             $('.'+itemClass+':eq('+i+')').addClass(itemHover);    //eq() jQuery遍历方法,下标从0开始
100                         }
101                         //只距离顶部50px,则默认为导航条的第0个对象 
102                         else if(varscroll < 50){    
103                             $('.'+itemClass).removeClass(itemHover);
104                             $('.'+itemClass+':eq(0)').addClass(itemHover);
105                         }
106                     }
107 
108                     //滚轮往下走,而且偏移量大于当前内容位置往上50px,且小于往下50px时,
109                     //即表示当前内容选中,为当前内容的在导航条上的项目添加active样式
110                     if(scrollDir == 'down' && varscroll > contentTop[i]-50 && varscroll < contentTop[i]+50) {
111                         $('.'+itemClass).removeClass(itemHover);
112                         $('.'+itemClass+':eq('+i+')').addClass(itemHover);
113                     }
114                     //如果滚轮往上走,则调用上面的函数判断
115                     if(scrollDir == 'up') {
116                         bottomView(i);
117                     }
118                 }
119             }
120 
121 
122             /* 参考示例
123             if(scrollDir == 'up') {
124                 for(var i=1;i < menuSize;i++)
125                 {
126                     //滚轮往上走的时候默认100以内的宽度让上方的项目增加active样式
127                     if(varscroll > $('#'+content[i-1]+'').offset().top && varscroll < $('#'+content[i]+'').offset().top-100){
128                         $('.'+itemClass).removeClass(itemHover);
129                         $('.'+itemClass+':eq('+(i-1)+')').addClass(itemHover);
130                     }
131                 }
132             }*/
133 
134 
135 
136             //两个IF判断滚轮位置是否超过导航条距离屏幕上方高度,
137             //如果超过了,就让导航条浮起来,相反就让导航条回到文档流中
138             if(vartop < varscroll + topMargin){
139                 $('.stuckMenu').addClass('isStuck');
140                 $('.stuckMenu').next().closest('div').css({
141                     'margin-top': stickyHeight + stickyMarginB + currentMarginT + 'px'
142                 }, 10);
143                 $('.stuckMenu').css("position","fixed");
144                 $('.isStuck').css({
145                     top: '0px'
146                 }, 10, function(){
147 
148                 });
149             };
150 
151             if(varscroll + topMargin < vartop){
152                 $('.stuckMenu').removeClass('isStuck');
153                 $('.stuckMenu').next().closest('div').css({
154                     'margin-top': currentMarginT + 'px'
155                 }, 10);
156                 $('.stuckMenu').css("position","relative");
157             };
158 
159         });
160     });
161 
162 });

 

posted @ 2016-07-19 10:52  shiddong  阅读(440)  评论(0编辑  收藏  举报