Stickup.js导航条重构增强

如上图,此图应用在客户端,使用stickup.js实现导航条的滚动,项目开始时遇到很多麻烦,首要的就是滚动条随着滑动效果遮盖下方的,这样做用户体验感很不好。考虑到该层面问题,对stickup进行了增强。
鼠标滑动下来并变成如下

源码如下,重要的地方我会使用红色字体标红。
// 问题:不支持一个页面中多个元素固定(已实现) // 不支持固定方向的设置 // 不支持回调事件(已实现) // 单页模式下,调整的定位是基于part参数的(重构后是基于html元素的data-menu) // 目前而言,许多操作是实时的——比如每次都重新查找、计算DOM // 这种方法对网页变动比较大的情景是非常适用的,但比较耗费性能 // // 目前为止,缺乏测试 jQuery(function($) { "use strict"; var Context = function() {}, _ctxList = {}, lastScrollTop = 0; Context.prototype = { // 配置参数 dataProperty: 'data-menu', itemClass: '', itemHover: '', marginTop: 0, beforeStick: null, afterStick: null, beforeUnstick: null, afterUnstick: null, topHeight: 0, //自定义距离顶部高度 // 预留参数 region: 'top', // 自动计算值 // 私有参数 _selector: '', _jqDom: null, _menuItems: [], _height: 0, _parentMarginTop: 0, _top: 0, _marginBottom: 0, onScroll: function(scrollDir, varscroll) { var contentView = null, testView = null, _me = this; // 计算并给适当元素添加 itemHover 类 if ( !! _me._menuItems && _me._menuItems.length > 0) { var offset = null, contentTop = 0, tmp_menuTarget = null; for (var i = 0; i < _me._menuItems.length; i++) { tmp_menuTarget = $('#' + $(_me._menuItems[i]).attr(_me.dataProperty)); offset = tmp_menuTarget.offset(); //减少滚动值 _______自定义_________ contentTop = !! offset ? offset.top - _me.topHeight : 0 - _me.topHeight; // 之前這裡定義了一個bottomView // 会在每次执行这个地方的时候都去创建一个函数 // 实际上是很没必要的性能损耗,所以这里将代码移动下面 if (scrollDir == 'down' && varscroll > contentTop - 50 && varscroll < contentTop + 50) { _me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover); _me._jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover); } if (scrollDir == 'up') { // 这里就是原来的bottomView代码 contentView = tmp_menuTarget.height() * 0.4; testView = contentTop - contentView; if (varscroll > testView) { _me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover); _me._jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover); } else if (varscroll < 50) { _me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover); _me._jqDom.find('.' + _me.itemClass + ':eq(0)').addClass(_me.itemHover); } } } } // 固定菜单栏目,使之固定(fixed) if (_me._top < varscroll + _me.marginTop) { if ( !! _me.beforeStick) _me.beforeStick.call(_me); _me._jqDom.addClass('isStuck'); if ( !! _me.afterStick) _me.afterStick.call(_me); _me._jqDom.next().closest('div').css({ 'margin-top': _me._height + _me._marginBottom + _me._parentMarginTop + 'px' }, 10); _me._jqDom.css("position", "fixed"); //_me._jqDom.css({ // top: '0px' //}, 10); //自定义的导航栏浮动的高度 _me._jqDom.css({ top: _me.topHeight }, 10); }; // 菜單欄目,使之不固定(relative) if (varscroll + _me.marginTop < _me._top) { if ( !! _me.beforeUnstick) _me.beforeUnstick.call(_me); _me._jqDom.removeClass('isStuck'); if ( !! _me.afterUnstick) _me.afterUnstick.call(_me); _me._jqDom.next().closest('div').css({ 'margin-top': _me._parentMarginTop + 'px' }, 10); _me._jqDom.css("position", "relative"); _me._jqDom.css({top: '0px'}, 10); }; } }; Context._init_ = function(dom, option, instance) { instance = instance || new Context(); var _me = instance, objn = 0; _me._jqDom = $(dom); //getting options if ( !! option) { _me._menuItems = _me._jqDom.find('[' + _me.dataProperty + ']'); if (option.topMargin != null) { if (option.topMargin == 'auto') { _me.marginTop = parseInt(_me._jqDom.css('margin-top')); } else { if (isNaN(option.topMargin) && option.topMargin.search("px") > 0) { _me.marginTop = parseInt(option.topMargin.replace("px", "")); } else if (!isNaN(parseInt(option.topMargin))) { _me.marginTop = parseInt(option.topMargin); } else { console.log("incorrect argument, ignored."); _me.marginTop = 0; } } } else { _me.marginTop = 0; } _me.itemClass = option.itemClass; _me.itemHover = option.itemHover; } else { console.log('warm:needs arguments'); } _me.dataProperty = option.dataProperty || _me.dataProperty; _me.region = option.region || _me.region; _me._height = parseInt(_me._jqDom.height()); _me._marginBottom = parseInt(_me._jqDom.css('margin-bottom')); _me._parentMarginTop = parseInt(_me._jqDom.next().closest('div').css('margin-top')); _me._top = parseInt(_me._jqDom.offset().top); //自定义 if(_me.topHeight != null){ _me.topHeight = parseInt(option.topHeight, 10);//_______自定义_________ } _ctxList[_me._selector] = _me; }; // 初始化各类参数,即解析options的值 $.fn.stickUp = function(options) { if (!_ctxList[this.selector]) Context._init_(this, options); } // 頁面滾動事件 $(document).on('scroll', function() { var scrollOffest = parseInt($(document).scrollTop()), scrollDir = scrollOffest > lastScrollTop ? 'down' : 'up'; for (var i in _ctxList) { _ctxList[i].onScroll(scrollDir, scrollOffest); } lastScrollTop = scrollOffest; }); });
按照正常思维来说,我们需要遍历一个容器的时候需要获取其中的数据的时候,是依次按照每个遍历,并romver掉不需要的参数,在以上段代码当中使用了find方法拿到class值,并判断,这样做的一个好处是提升了比较性。
浙公网安备 33010602011771号