上文提供了一个改进版的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().top + 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().top) + getPageScrollTop() - offsetTop);
}); /**
* Math.floor是解决rect.top或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.top) <= 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.top的值60.2222299999,offsetTop的值是60,期望是curRect.top <= offsetTop这个条件能够成立,因为小数的原因,所以它不成立。

感谢您的阅读:)

代码下载

基于sticky组件,实现带sticky效果的tab导航和滚动导航的更多相关文章

  1. 开源一个简单的react-native 菜单栏抽屉组件,带缩放效果

    效果如图所示,源码地址:https://github.com/pofabs/PoSideMenu

  2. sticky组件的改进实现

    上上篇博客介绍了一个sticky组件的简洁实现,经过这两天的思考,发现上次提供的实现还有较多不足的地方,另外跟别的网站上实现的效果在取消固定的时候也有一些不同,上次提供的取消固定的处理方式不好,本文在 ...

  3. 利用getBoundingClientRect方法实现简洁的sticky组件

    补充于2016-03-20: 本文实现有不足,不完美的地方,请在了解本文相关内容后,移步阅读<sticky组件的改进实现>了解更佳的实现. sticky组件,通常应用于导航条或者工具栏,当 ...

  4. 自己写的中间层..基于通讯组件 RTC

    273265088 我用原生Listbox与你的组件组合...创造了奇迹..搞了一个非常复杂的 UI .. 每个item高度 包括里面的元素 以及事件都是动态的搞了好几个小时感觉UI 非常完美比客户要 ...

  5. 基于vue与vux做的可滑动tab组件(附源码)

    背景 前不久,刚完成了一个商品列表+购物车功能的页面,因为一级商品分类在顶部tab中显示,可滑动,间距可定制,如下图所示: 定制的tab需求如下: 1. 每个tab-item的间距是相同的,可定制 2 ...

  6. 基于forms组件和Ajax实现注册功能

    一.基于forms组件的注册页面设计 1.运用forms组件的校验字段功能实现用户注册 views.py:    (在钩子中代码解耦,将form放在cnblog/blog/Myforms.py中) f ...

  7. [开源] 基于Layui组件封装的后台模版,HG-Layui-UI通用后台管理框架V1.0版

    HG框架简介 HG-Layui-UI框架,是基于layui最新版UI搭建的一套通用后台管理框架,借鉴了市面上各大主流框架风格,采用iframe标签页实现,保留了传统开发模式的简单实用性. 为快速开发减 ...

  8. Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条

    本博主在一次个人移动端项目中,遇到这么一个需求:希望自己的项目中,头部导航条的效果可以像今日头条那样,横向滚动! 对于这样的效果,在各大移动端项目中几乎是随处可见,为什么呢? 我们都知道,对于移动端也 ...

  9. 十七、.net core(.NET 6)搭建基于Quartz组件的定时调度任务

     搭建基于Quartz组件的定时调度任务 先在package包项目下,添加Quartz定时器组件: 新建类库项目Wsk.Core.QuartzNet,并且引用包类库项目.然后新建一个中间调度类,叫Qu ...

随机推荐

  1. shared_ptr

    省去对象指针的显示delete typedef tr1::shared_ptr<int> IntPtr; IntPtr fun() { IntPtr p = new int(3); ret ...

  2. 关于HTML是什么,能做什么

    HTML(Hyper Text Mark-up Language )即超文本标记语言,是 WWW 的描述语言,由 Tim Berners-lee提出.设计 HTML 语言的目的是为了能把存放在一台电脑 ...

  3. 搭建Linux+Jexus+MariaDB+ASP.NET[LJMA]环境

    备注:,将我的博客内容整理成册,首先会在博客里优先发布,后续可能的话整理成电子书,主要从linux的最基础内容开始进入Linux的Mono开发方面的话题.本文是我整理博客内容的一篇文章. LJMA 是 ...

  4. 非常郁闷的 .NET中程序集的动态加载

    记载这篇文章的原因是我自己遇到了动态加载程序集的问题,而困扰了一天之久. 最终看到了这篇博客:http://www.cnblogs.com/brucebi/archive/2013/05/22/Ass ...

  5. 玩转JavaScript OOP[0]——基础类型

    前言 long long ago,大家普遍地认为JavaScript就是做一些网页特效的.处理一些事件的.我身边有一些老顽固的.NET程序员仍然停留在这种认知上,他们觉得没有后端开发肯定是构建不了系统 ...

  6. 从“差不多了”到 正式发布 -- 新浪微博WinPhone UWP版诞生记

    本文粗略记述了UWP团队从接手新浪微博项目到发布第一版的过程.本文不是技术贴,而是回顾“软件工程周期失控是一种怎样的体验”. 接手新项目:捡了个大便宜 2016年1月份,UWP team开始接手新浪微 ...

  7. 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...

  8. java中 用telnet 判断服务器远程端口是否开启

    package net.jweb.common.util; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...

  9. iOS瀑布流实现(Swift)

    这段时间突然想到一个很久之前用到的知识-瀑布流,本来想用一个简单的方法,发现自己走入了歧途,最终只能狠下心来重写UICollectionViewFlowLayout.下面我将用两种方法实现瀑布流,以及 ...

  10. Trace1:Default Trace

    sql server trace 是一个轻量级的追踪工具,对追踪数据库的行为很有用,因此,sql server内置一个trace(default trace). 1,sql server 内置Defa ...