基于jquery的跟随屏幕滚动代码


Posted in Javascript onJuly 24, 2012

那么这是怎么实现的呢?本文将引用乌徒帮的跟随屏幕滚动代码,对此效果做详解。
一、原始代码
下面是乌徒帮的跟随屏幕滚动代码,它的作用域为乌徒帮网页两侧的边栏,以及双击屏幕后的右侧隐藏栏。

var $catalogueOffsetTop = $('aside#catalogue').offset().top; 
var $archiveOffestTop = $('aside#archive').offset().top; 
var $archiveOffestLeft = $('aside#archive').offset().left; 
$(window).bind('scroll resize',function(){ 
// #right-area的跟随屏幕滚动效果 
if($('#right-area').height() <= $(window).height()){ 
$('#right-area').stop(true,true).animate({'top': $(document).scrollTop() + 'px'},800); 
}else if($('#right-area').height() > $(window).height() && $('#right-area').height() < $(document).height()){ 
// 这段范围内是最关键的,允许滑动 
if(($(document).scrollTop() + $(window).height()) <= $('#right-area').height()){ 
$('#right-area').stop(true,true).css('top','0'); 
}else if(($(document).scrollTop() + $(window).height()) < $(document).height()){ 
$right_top = $(document).scrollTop() + $(window).height() - $('#right-area').height(); 
$('#right-area').stop(true,true).animate({'top': $right_top + 'px'},800); 
}else{ 
$right_top = $(document).height() - $('#right-area').height(); 
$('#right-area').stop(true,true).css({'top': $right_top + 'px'}); 
//alert($(document).scrollTop() + $(window).height() - $(document).height()); 
} 
}else if($('#right-area').height() >= $(document).height()){ 
$('#right-area').height($(document).height()).stop(true,true).css({'overflow':'hidden','overflow-y':'scroll'}); 
} 
if($(document).scrollLeft() == 0){ // 只有在屏幕处于左侧的时候才进行下面的跟随滚动,同时需要注意下面的if($(window).width() > 1024),是为了防止在小屏幕下还发生这种变化 
// aside#catalogue的上下滑动 
if($('aside#catalogue').outerHeight() < $(window).height()){ 
if($(document).scrollTop() <= $catalogueOffsetTop){ 
$('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); 
if($(window).width() > 1024)$('#main').css({'padding-left':'0'}); 
}else{ 
$('aside#catalogue').css({'position':'fixed','top':'0'}); 
if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); 
} 
}else if($('aside#catalogue').height() >= $(window).height() && $('aside#catalogue').outerHeight() < ($('footer').offset().top - $catalogueOffsetTop)){ 
if(($(document).scrollTop() + $(window).height()) <= ($('aside#catalogue').outerHeight() + $catalogueOffsetTop)){ 
$('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); 
if($(window).width() > 1024)$('#main').css({'padding-left':'0'}); 
}else if(($(document).scrollTop() + $(window).height()) < $('footer').offset().top){ 
$catalogue_top = $(window).height() - $('aside#catalogue').outerHeight() - 20; 
$('aside#catalogue').css({'position':'fixed','top': $catalogue_top + 'px'}); 
if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); 
}else{ 
$catalogue_top = $(window).height() - $('aside#catalogue').outerHeight() - 20 - ($(document).height() - $('footer').offset().top); 
$('aside#catalogue').css({'position':'fixed','top':$catalogue_top + 'px'}); 
if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); 
} 
} 
// aside#archive的上下滑动 
if($('aside#archive').outerHeight() < $(window).height()){ 
if($(document).scrollTop() <= $archiveOffestTop){ 
$('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); 
}else{ 
$('aside#archive').css({'position':'fixed','top':'0','left':$archiveOffestLeft + 'px'}); 
} 
}else if($('aside#archive').height() >= $(window).height() && $('aside#archive').outerHeight() < ($('footer').offset().top - $archiveOffestTop)){ 
if(($(document).scrollTop() + $(window).height()) <= ($('aside#archive').outerHeight() + $archiveOffestTop)){ 
$('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); 
}else if(($(document).scrollTop() + $(window).height()) < $('footer').offset().top){ 
$catalogue_top = $(window).height() - $('aside#archive').outerHeight(); 
$('aside#archive').css({'position':'fixed','top': $catalogue_top + 'px','left':$archiveOffestLeft + 'px'}); 
}else{ 
$catalogue_top = $(window).height() - $('aside#archive').outerHeight() - ($(document).height() - $('footer').offset().top); 
$('aside#archive').css({'position':'fixed','top':$catalogue_top + 'px','left':$archiveOffestLeft + 'px'}); 
} 
} 
}else{ // 如果屏幕不处于左侧,就让这两个跟随归位 
$('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); 
$('#main').css({'padding-left':'0'}); 
$('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); 
} 
}).scroll().resize();

网络上有很多相关的代码,更有7行代码解决此问题的方法,甚至还有通用性的插件来实现此效果。然而它们都太过普遍化,对于不同的网站,特殊性不同,在一些细节上要做更多的考虑。

二、选择用什么方式跟随屏幕滚动
方案有三种:

1、使用position:absolute;然后对top值进行动态赋值;
2、使用position:fixed;然后对top值进行动态赋值;
3、对padding-top或margin-top进行动态赋值;

前两种都是用到了postion对元素的位置进行安排,和float一样,position将元素从正常的文本流中拖出来。而padding或margin的方法则是控制元素的边距来实现。到底哪一种好呢?

使用position:absolute;会出现滚动时发生抖动(火狐中不会) ,使用padding-top时会让有背景的元素看上去难看,也会发生抖动,使用position:fixed不支持IE6,使用margin-top没有尝试过,应该会发生抖动。本段代码选择的是position:fixed,唯一不发生抖动的方案,但是在IE6下不会有该效果。

三、要考虑的情况
之所以乌徒帮要将本站的代码拿出来讲解,是因为网上的代码没有具体分析,很多问题都没有考虑到。

1、要跟随的元素的高度和屏幕的高度进行比较

网上所有的代码考虑的是该区域的高度小于窗口高度的情况,因此代码很简单。当区域高度等于和大于窗口高度时,我们又会有新的考虑。

2、如果区域高度超出窗口,何时开始跟随滚动?

这要看我们想给用户展示什么,如果是一个广告,如果是一段文字,如果是一个列表。我的设计是,当屏幕往下滚动,但是还没有将要显示的元素全部显示完整时,不进行任何效果,当屏幕滚动到元素的底部临界处时,效果触发,再往下滚动时,元素的底端和屏幕的底端对齐,元素的下部一直呈现在屏幕内。当然,不同的网页,你的设计自然不同,你也可能设计为,向下滚动时先没有效果,当滚动到某一个广告之后,这个广告和屏幕顶端对齐跟随滚动。
基于jquery的跟随屏幕滚动代码
图一 跟随屏幕滚动逻辑设计图

从图一中我们来看一下这一设计思路。图中绿色部分为要跟随滚动的区域,灰色部分为整个网页,浅灰色部分为屏幕(能看到的区域)我们通过向下移动浅灰色的屏幕来模拟往下滚动滚动条。在①的阶段为初始阶段,这个时候网页一切照初始运作,没有任何动作。到②的阶段,屏幕向下滚动到一个临界点,即要跟随滚动区域的最低端。第③阶段是滚动过临界点之后,元素开始跟随屏幕滚动,我们可以看到,元素的底端和屏幕的底端对齐,元素的顶端已经看不到。第④个阶段的屏幕滚动到底部,可以想象,网页的底部是存在一些版权信息的,元素不能跟随滚到底部把这些信息遮住,因此在红线的地方就不再跟随滚动。

这是屏幕向下滚动的示意图,当屏幕向上滚动时,这是这个顺序的逆向。但是还有另外一个考虑,当屏幕在向上滚动时实现和向下滚动初始状的一种效果,即临界点是此时④中的绿色区域顶端,向上滚动时屏幕顶端和元素顶端对齐。出于技术难度的考虑,乌徒帮没有实现这一效果。

3、数和量的计算

在滚动时,我们要掌握好那些量是变化的,哪些又不变,在不变中找变,在变中找不变,总之要保持头脑清晰,分清如何去计算各种高度关系。

在图一中,我用了一条蓝色竖线来辅助高度计算,用红色的线指示屏幕和元素的位置,将蓝色竖线分成了a、b、c、d、e、f六段。那么他们之间有着哪些变化数量关系呢?(我们将绿色区域的元素定义为#myDiv,将版权信息在内的底部定义为#footer)

a+b+c+d+e+f=$(document).height();//文档高度,固定值

a= $('#myDiv').offset().top;//#myDiv顶部到文档顶部的初始值,随着滚动,$('#myDiv').offset().top将会变化 b=$('#myDiv').height();//元素的高度,固定值 
a+b+c=$(window).scrollTop()=$(docment).scrollTop();//滚动条的位置,即文档顶端到当前屏幕顶端的距离,不断变化中 
d=$(window).height();//屏幕的高度,固定值 
f=$('#footer').height();//#footer的高度,固定值 
a+b+c+d+e=$('#footer').offset().top=$(document).height()-$('#footer').height();//#footer顶部到文档顶部的距离,固定值,不过需要注意的是,$('#footer').offset().top+$('#footer').height()并非一定等于$(document).height(),你要看#footer下面是否已经没有了空白。

在整个变化过程中,变化的值只有$(window).scrollTop()=$(docment).scrollTop()和$('#myDiv').offset().top,因此我们要抓住这些值之间的加减数量关系,做好逻辑判断和赋值。

4、值在什么时候获取

你可以看到,我在scroll事件之前事先获取了

var $catalogueOffsetTop = $('aside#catalogue').offset().top; 
var $archiveOffestTop = $('aside#archive').offset().top; 
var $archiveOffestLeft = $('aside#archive').offset().left;

正是由于他们在scroll事件发生时会发生变化,因此要提前存放在变量中。

四、特殊情况特殊考虑

在写出这么多代码之前,我曾想过写出一个可以通用的代码,然而事情并非那么简单,在乌徒帮中,三个要滚动 的区域都具有特殊性,因此必须认真考虑他们的事件逻辑和仔细赋值。

1、元素是否自由随意

由于乌徒帮双击屏幕滑向右侧时出现的区域是自由的,顶部和底部没有阻挡信息,因此我们的处理更方便一些,不用获取顶部距离的初始值和考虑滚到底部时空出一段。但是仍然要考虑下面第2点,屏幕和元素高度的比较。

而对于边侧栏的滚到,我们要考虑边侧栏顶部到文档顶部还有一段距离,底部还有版权信息。滚到的位置要通过上文获得的值,再配合css中获得的值进行精确计算。

2、判断元素的高度和屏幕高度之间的关系

当元素高度小的时候,我们的处理比较简单,只需要将元素顶端和屏幕顶端对齐,和上面第1点结合,也会出现不同的情况:如果元素顶部到文档顶部还有一段距离的话,我们还不能屏幕一滚动就开始让它和屏幕顶端对齐,而必须滚到它的顶端这个临界点的时候才可以开始。

而当元素的高度大于屏幕的高度的时候,我们要进行更复杂的判断,和第1点判断何时开始跟随滚动:只有当屏幕的底端和元素底端对齐时,元素开始跟随屏幕滚动。

但是还有一种情况,即元素的高度超出了我们想要的高度,我们可以使用overflow来对元素进行处理,这时我们通过元素的高度和页面中一些固定值的比较来处理这一环节。乌徒帮通过比较右侧元素的高度和底部的关系来进行overflow的处理:

...... 
}else if($('#right-area').height() >= ($('footer').offset().top + $('footer').height())){ 
$('#right-area').height($('footer').offset().top + $('footer').height()).stop(true,true).css({'overflow':'hidden','overflow-y':'scroll'}); 
}

3、自己网页内特殊情况的变化

乌徒帮由于左右还可以滚动,因此产生了一系列问题,position:fixed时左右方向上元素的距离并没有固定值,因此在进行左右滚动时,元素会遮住滚动完的屏幕,因此我又对$(document).scrollLeft()进行了判断,进行了一些处理。

另外,乌徒帮还是一个自适应的网页设计网站,在不同宽度的屏幕上显示的效果也不同,js的特点是当屏幕发生变化时仍然起作用,因此,我也增加了屏幕宽度的判断。

总结
在跟随屏幕滚动这个问题上,原始的思路是很简单的,即通过本文列举的三种方案进行位置或距离的动态改变,然而,要在具体细节上把握好,必须对动态变化中的各个数值有所把握。于此同时,结合自己的网页,对不同情况下的动态效果有一个好的设计和规划,也是实现跟随屏幕滚动的关键环节。

Javascript 相关文章推荐
img的onload的另类用法
Jan 10 Javascript
js实现跨域访问的三种方法
Dec 09 Javascript
基于javascript实现九九乘法表
Mar 27 Javascript
html5+javascript实现简单上传的注意细节
Apr 18 Javascript
关于backbone url请求中参数带有中文存入数据库是乱码的快速解决办法
Jun 13 Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 Javascript
Javascript单例模式的介绍和实例
Oct 08 Javascript
js仿小米手机上下滑动效果
Feb 05 Javascript
angular.js实现购物车功能
Oct 23 Javascript
解决JavaScript中0.1+0.2不等于0.3问题
Oct 23 Javascript
基于Vue-cli快速搭建项目的完整步骤
Nov 03 Javascript
package.json中homepage属性的作用详解
Mar 11 Javascript
基于JQuery的类似新浪微博展示信息效果的代码
Jul 23 #Javascript
基于jquery自定义图片热区效果
Jul 21 #Javascript
Js四则运算函数代码
Jul 21 #Javascript
Javascript对象中关于setTimeout和setInterval的this介绍
Jul 21 #Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
Jul 21 #Javascript
Javascript中找到子元素在父元素内相对位置的代码
Jul 21 #Javascript
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 #Javascript
You might like
用PHP实现WEB动态网页静态
2006/10/09 PHP
PHP SQLite类
2009/05/07 PHP
php缓冲 output_buffering和ob_start使用介绍
2014/01/30 PHP
PHP中遇到BOM、编码导致json_decode函数无法解析问题
2014/07/02 PHP
Zend Framework实现将session存储在memcache中的方法
2016/03/22 PHP
PHP实现倒计时功能
2020/11/16 PHP
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
javascript基于HTML5 canvas制作画箭头组件
2014/06/25 Javascript
js时钟翻牌效果实现代码分享
2020/07/31 Javascript
什么是JavaScript中的结果值?
2016/10/08 Javascript
JavaScript中浅讲ajax图文详解
2016/11/11 Javascript
webpack多页面开发实践
2017/12/18 Javascript
Node.js使用MySQL连接池的方法实例
2018/02/11 Javascript
javascript填充默认头像方法
2018/02/22 Javascript
Angular PWA使用的Demo示例
2019/01/31 Javascript
javascript实现手动点赞效果
2019/04/09 Javascript
js作用域和作用域链及预解析
2019/04/11 Javascript
详解Vue前端生产环境发布配置实战篇
2019/05/07 Javascript
使用Python生成XML的方法实例
2017/03/21 Python
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
Tensorflow 实现修改张量特定元素的值方法
2018/07/30 Python
对Python w和w+权限的区别详解
2019/01/23 Python
Python 编程速成(推荐)
2019/04/15 Python
详解python实现交叉验证法与留出法
2019/07/11 Python
导入tensorflow:ImportError: libcublas.so.9.0 报错
2020/01/06 Python
Pycharm及python安装详细步骤及PyCharm配置整理(推荐)
2020/07/31 Python
西班牙在线宠物商店:zooplus.es
2017/02/24 全球购物
Blank NYC官网:夹克、牛仔裤等
2020/12/16 全球购物
汉语言文学毕业生自荐信范文
2014/03/24 职场文书
应届生求职自荐信范文
2014/04/07 职场文书
校园文明倡议书
2014/05/16 职场文书
公司领导班子召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
开会通知短信大全
2015/04/20 职场文书
幼儿园大班教师随笔
2015/08/14 职场文书
党员干部学习心得体会
2016/01/23 职场文书