用sticky.js实现头部导航栏固定

在页面中,如果页面长度过大,滑动页面时,头部导航栏则会跟着划走。

我的头部导航栏代码为:

1 <div class="headbar">
2        <center class="headbarTitle">通讯录</center>
3 </div>

 

 

 固定头部导航栏的方法:引入sticky.js,再加上

1 //头部导航固定
2 $(".headbar").sticky(
3 {
4     topSpacing: 0
5 })

即可。

sticky.js代码如下:

  1 (function (factory) {
  2   if (typeof define === 'function' && define.amd) {
  3     // AMD. Register as an anonymous module.
  4     define(['jquery'], factory);
  5   } else if (typeof module === 'object' && module.exports) {
  6     // Node/CommonJS
  7     module.exports = factory(require('jquery'));
  8   } else {
  9     // Browser globals
 10     factory(jQuery);
 11   }
 12 }(function ($) {
 13   var slice = Array.prototype.slice; // save ref to original slice()
 14   var splice = Array.prototype.splice; // save ref to original slice()
 15 
 16   var defaults = {
 17     topSpacing: 0,
 18     bottomSpacing: 0,
 19     className: 'is-sticky',
 20     wrapperClassName: 'sticky-wrapper',
 21     center: false,
 22     getWidthFrom: '',
 23     widthFromWrapper: true, // works only when .getWidthFrom is empty
 24     responsiveWidth: false,
 25     zIndex: '100'
 26   },
 27     $window = $(window),
 28     $document = $(document),
 29     sticked = [],
 30     windowHeight = $window.height(),
 31     scroller = function () {
 32       var scrollTop = $window.scrollTop(),
 33         documentHeight = $document.height(),
 34         dwh = documentHeight - windowHeight,
 35         extra = (scrollTop > dwh) ? dwh - scrollTop : 0;
 36 
 37       for (var i = 0, l = sticked.length; i < l; i++) {
 38         var s = sticked[i],
 39           elementTop = s.stickyWrapper.offset().top,
 40           etse = elementTop - s.topSpacing - extra;
 41 
 42         //update height in case of dynamic content
 43         s.stickyWrapper.css('height', s.stickyElement.outerHeight());
 44 
 45         if (scrollTop <= etse) {
 46           if (s.currentTop !== null) {
 47             s.stickyElement
 48               .css({
 49                 'width': '',
 50                 'position': '',
 51                 'top': '',
 52                 'z-index': ''
 53               });
 54             s.stickyElement.parent().removeClass(s.className);
 55             s.stickyElement.trigger('sticky-end', [s]);
 56             s.currentTop = null;
 57           }
 58         } else {
 59           var newTop = documentHeight - s.stickyElement.outerHeight() -
 60             s.topSpacing - s.bottomSpacing - scrollTop - extra;
 61           if (newTop < 0) {
 62             newTop = newTop + s.topSpacing;
 63           } else {
 64             newTop = s.topSpacing;
 65           }
 66           if (s.currentTop !== newTop) {
 67             var newWidth;
 68             if (s.getWidthFrom) {
 69               padding = s.stickyElement.innerWidth() - s.stickyElement.width();
 70               newWidth = $(s.getWidthFrom).width() - padding || null;
 71             } else if (s.widthFromWrapper) {
 72               newWidth = s.stickyWrapper.width();
 73             }
 74             if (newWidth == null) {
 75               newWidth = s.stickyElement.width();
 76             }
 77             s.stickyElement
 78               .css('width', newWidth)
 79               .css('position', 'fixed')
 80               .css('top', newTop)
 81               .css('z-index', s.zIndex);
 82 
 83             s.stickyElement.parent().addClass(s.className);
 84 
 85             if (s.currentTop === null) {
 86               s.stickyElement.trigger('sticky-start', [s]);
 87             } else {
 88               // sticky is started but it have to be repositioned
 89               s.stickyElement.trigger('sticky-update', [s]);
 90             }
 91 
 92             if (s.currentTop === s.topSpacing && s.currentTop > newTop || s.currentTop === null && newTop < s.topSpacing) {
 93               // just reached bottom || just started to stick but bottom is already reached
 94               s.stickyElement.trigger('sticky-bottom-reached', [s]);
 95             } else if (s.currentTop !== null && newTop === s.topSpacing && s.currentTop < newTop) {
 96               // sticky is started && sticked at topSpacing && overflowing from top just finished
 97               s.stickyElement.trigger('sticky-bottom-unreached', [s]);
 98             }
 99 
100             s.currentTop = newTop;
101           }
102 
103           // Check if sticky has reached end of container and stop sticking
104           var stickyWrapperContainer = s.stickyWrapper.parent();
105           var unstick = (s.stickyElement.offset().top + s.stickyElement.outerHeight() >= stickyWrapperContainer.offset().top +
106             stickyWrapperContainer.outerHeight()) && (s.stickyElement.offset().top <= s.topSpacing);
107 
108           if (unstick) {
109             s.stickyElement
110               .css('position', 'absolute')
111               .css('top', '')
112               .css('bottom', 0)
113               .css('z-index', '');
114           } else {
115             s.stickyElement
116               .css('position', 'fixed')
117               .css('top', newTop)
118               .css('bottom', '')
119               .css('z-index', s.zIndex);
120           }
121         }
122       }
123     },
124     resizer = function () {
125       windowHeight = $window.height();
126 
127       for (var i = 0, l = sticked.length; i < l; i++) {
128         var s = sticked[i];
129         var newWidth = null;
130         if (s.getWidthFrom) {
131           if (s.responsiveWidth) {
132             newWidth = $(s.getWidthFrom).width();
133           }
134         } else if (s.widthFromWrapper) {
135           newWidth = s.stickyWrapper.width();
136         }
137         if (newWidth != null) {
138           s.stickyElement.css('width', newWidth);
139         }
140       }
141     },
142     methods = {
143       init: function (options) {
144         return this.each(function () {
145           var o = $.extend({}, defaults, options);
146           var stickyElement = $(this);
147 
148           var stickyId = stickyElement.attr('id');
149           var wrapperId = stickyId ? stickyId + '-' + defaults.wrapperClassName : defaults.wrapperClassName;
150           var wrapper = $('<div></div>')
151             .attr('id', wrapperId)
152             .addClass(o.wrapperClassName);
153 
154           stickyElement.wrapAll(function () {
155             if ($(this).parent("#" + wrapperId).length == 0) {
156               return wrapper;
157             }
158           });
159 
160           var stickyWrapper = stickyElement.parent();
161 
162           if (o.center) {
163             stickyWrapper.css({ width: stickyElement.outerWidth(), marginLeft: "auto", marginRight: "auto" });
164           }
165 
166           if (stickyElement.css("float") === "right") {
167             stickyElement.css({ "float": "none" }).parent().css({ "float": "right" });
168           }
169 
170           o.stickyElement = stickyElement;
171           o.stickyWrapper = stickyWrapper;
172           o.currentTop = null;
173 
174           sticked.push(o);
175 
176           methods.setWrapperHeight(this);
177           methods.setupChangeListeners(this);
178         });
179       },
180 
181       setWrapperHeight: function (stickyElement) {
182         var element = $(stickyElement);
183         var stickyWrapper = element.parent();
184         if (stickyWrapper) {
185           stickyWrapper.css('height', element.outerHeight());
186         }
187       },
188 
189       setupChangeListeners: function (stickyElement) {
190         if (window.MutationObserver) {
191           var mutationObserver = new window.MutationObserver(function (mutations) {
192             if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) {
193               methods.setWrapperHeight(stickyElement);
194             }
195           });
196           mutationObserver.observe(stickyElement, { subtree: true, childList: true });
197         } else {
198           if (window.addEventListener) {
199             stickyElement.addEventListener('DOMNodeInserted', function () {
200               methods.setWrapperHeight(stickyElement);
201             }, false);
202             stickyElement.addEventListener('DOMNodeRemoved', function () {
203               methods.setWrapperHeight(stickyElement);
204             }, false);
205           } else if (window.attachEvent) {
206             stickyElement.attachEvent('onDOMNodeInserted', function () {
207               methods.setWrapperHeight(stickyElement);
208             });
209             stickyElement.attachEvent('onDOMNodeRemoved', function () {
210               methods.setWrapperHeight(stickyElement);
211             });
212           }
213         }
214       },
215       update: scroller,
216       unstick: function (options) {
217         return this.each(function () {
218           var that = this;
219           var unstickyElement = $(that);
220 
221           var removeIdx = -1;
222           var i = sticked.length;
223           while (i-- > 0) {
224             if (sticked[i].stickyElement.get(0) === that) {
225               splice.call(sticked, i, 1);
226               removeIdx = i;
227             }
228           }
229           if (removeIdx !== -1) {
230             unstickyElement.unwrap();
231             unstickyElement
232               .css({
233                 'width': '',
234                 'position': '',
235                 'top': '',
236                 'float': '',
237                 'z-index': ''
238               });
239           }
240         });
241       }
242     };
243 
244   // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer):
245   if (window.addEventListener) {
246     window.addEventListener('scroll', scroller, false);
247     window.addEventListener('resize', resizer, false);
248   } else if (window.attachEvent) {
249     window.attachEvent('onscroll', scroller);
250     window.attachEvent('onresize', resizer);
251   }
252 
253   $.fn.sticky = function (method) {
254     if (methods[method]) {
255       return methods[method].apply(this, slice.call(arguments, 1));
256     } else if (typeof method === 'object' || !method) {
257       return methods.init.apply(this, arguments);
258     } else {
259       $.error('Method ' + method + ' does not exist on jQuery.sticky');
260     }
261   };
262 
263   $.fn.unstick = function (method) {
264     if (methods[method]) {
265       return methods[method].apply(this, slice.call(arguments, 1));
266     } else if (typeof method === 'object' || !method) {
267       return methods.unstick.apply(this, arguments);
268     } else {
269       $.error('Method ' + method + ' does not exist on jQuery.sticky');
270     }
271   };
272   $(function () {
273     setTimeout(scroller, 0);
274   });
275 }));

 

posted @ 2019-10-24 15:48  罗毅豪  阅读(1732)  评论(0编辑  收藏  举报