使用Sticky组件实现带sticky效果的tab导航和滚动导
sticky组件,通常应用于导航条或者工具栏,当网页在某一区域滚动的时候,将导航条或工具栏这类元素固定在页面顶部或底部,方便用户快速进行这类元素提供的操作。
在这篇文章提供了一个改进版的sticky组件,并将演示效果应用到了自己的博客。有了类似sticky的这种简单组件,我们就可以在利用它开发更丰富的效果,比如本文要介绍的tab导航和滚动导航。实现简单,演示效果如下
tab导航(对应tab-sticky.html)
滚动导航(对应nav-scroll-sticky.html)
1. tab导航的实现
tab导航的需求是在点击导航项的时候,除了切换tab内容,还要控制滚动,将要显示的tab内容置顶,并且要刚好显示在sticky元素的下边。由于demo是用bootstrap做的,bootstrap提供的tab组件非常简单好用,我们可以在tab组件提供的shown.bs.tab的事件回调里做滚动控制处理,所以这个效果实现起来比较容易
<script> var $target = $('#target'); new Sticky('#sticky', { unStickyDistance: 60, target: $target, wait: 1, isFixedWidth: false, getStickyWidth: function($elem) { return $elem.parent()[0].offsetWidth; } }); $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) { window.scrollTo(0, $target[0].getBoundingClientRect(). + getPageScrollTop() + 1); }); function getPageScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; } </script>
html结构
2. 滚动导航实现
滚动导航相对麻烦一些,tab组件里面,只会显示与当前激活的tab项对应的tab内容,而滚动导航里面,要导航的所有内容都是已经在页面中渲染完毕的,它的需求是
1)点击导航项的时候,控制页面滚动,自动将与点击的导航项对应的内容置顶显示,并且要刚好显示在sticky元素的下边;
2)页面滚动的时候,根据当前显示的导航内容自动给相应的导航项添加active样式。
尽管听起来复杂,demo中的实现还是比较容易
<script> var $sticky = $('#sticky'); var $target = $('#target'); new Sticky($sticky, { unStickyDistance: 60, target: $target, wait: 1, isFixedWidth: false, getStickyWidth: function ($elem) { return $elem.parent()[0].offsetWidth; } }); var offsetTop = 60; //实现点击tab项自动滚动到导航内容的效果 $sticky.on('click', 'a', function (e) { e.preventDefault(); var $this = $(e.currentTarget); var $parent = $this.parent(); if($parent.hasClass('active')) return; $sticky.find('li.active').removeClass('active'); $parent.addClass('active'); var target = $this.data('target') || $this.attr('href'); var $target = $(target); window.scrollTo(0, Math.floor($target[0].getBoundingClientRect().) + getPageScrollTop() - offsetTop); }); / Math.floor是解决rect.或rect.bottom带小数问题 / //实现滚动时根据当前显示的导航内容自动给相应的导航项添加active样式 $(window).scroll(throttle(function(){ var $curItem = $sticky.find('a').filter('[href=' + getCurTarget() + ']'); var $parent = $curItem.parent(); if($parent.hasClass('active')) return; //的blur是为了去掉:active及:focus伪类的样式 $sticky.find('li.active').removeClass('active').find('a').trigger('blur'); $parent.addClass('active'); },1)); //获取当前显示的导航内容元素的id function getCurTarget() { for(var targets = ['#First', '#Second', '#Third'], i = 0, l = targets.length; i < l; i++) { var curRect = $(targets[i])[0].getBoundingClientRect(); if(Math.floor(curRect.) <= offsetTop && Math.floor(curRect.bottom) > offsetTop) { return targets[i]; } } return targets[0]; } function getPageScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; } //这个函数在实际工作中是应该抽出来的,否则sticky.js里面还有一份重复的 function throttle(func, wait) { var timer = null; return function () { var self = this, args = arguments; if (timer) clearTimeout(timer); timer = setTimeout(function () { return typeof func === 'function' && func.apply(self, args); }, wait); } } </script>
html结构
3.
本文结合sticky组件,提供了2种导航效果实现,兼容IE9+,firefox以及chrome,感兴趣可以下载源码再去详细了解。在实现tab导航的时候,因为有bs的tab组件所以实现起来非常容易,也没有必要把sticky跟tab组件再封装起来形成一个新组件,毕竟效果的实现代码已经比较简单了。在实现滚动导航的时候,因为没有用tab组件,所以滚动导航的那两个需求点都是单独实现的,在实际情况中,这两个功能可以封装成2个独立的组件或者1个组件,这样就能把实现代码写的像tab导航那样简单,不过本文没有再深入去介绍这两个组件的写法,因为这不是本文主要想介绍的内容,虽然我很想这么做,后续肯定会再写博客来介绍这两个组件,简单的东西不造一下轮子,简直是浪费机会。在实现这两个效果的时候,也有2点收获
1)firefox以及IE,先让网页,然后再刷新,虽然网页还会显示在刷新的位置,不会触发scroll事件,所以今后做scroll相关的组件,一定在组件初始化的时候主动掉一次scroll相关的回调;
2)getBoundingClientRect返回的rect对象相关的值,在IE和firefox下,都可能是小数,比如60.2222299999,这样的数,在进行判断的时候可能会跟预期情况不符,导致一些意外的BUG,如果不是特别严谨的话,可以用Math.floor对这些值进行取整,然后再用来计算或者判断。比如滚动导航实现中,rect.的值60.2222299999,offsetTop的值是60,期望是curRect. <= offsetTop这个条件能够成立,因为小数的原因,所以它不成立。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程