jquery跟随屏幕滚动效果的实现代码


Posted in Javascript onApril 13, 2016

我们在很多网站看到,当我们滚动网页时,网页内的广告或某个小区域并不会消失,而是浮动在屏幕的某个地方,特别是一些局域广告。那么这是怎么实现的呢?本文将引用乌徒帮的跟随屏幕滚动代码,对此效果做详解。

一、原始代码

下面是乌徒帮的跟随屏幕滚动代码,它的作用域为乌徒帮网页两侧的边栏,以及双击屏幕后的右侧隐藏栏。

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的特点是当屏幕发生变化时仍然起作用,因此,我也增加了屏幕宽度的判断。

总结

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

以上这篇jquery跟随屏幕滚动效果的实现代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery利用event.which方法获取键盘输入值的代码
Oct 09 Javascript
jQuery setTimeout()函数使用方法
Apr 07 Javascript
url参数中有+、空格、=、%、&amp;、#等特殊符号的问题解决
May 15 Javascript
JavaScript中toString()方法的使用详解
Jun 05 Javascript
CSS3实现动态背景登录框的代码
Jul 28 Javascript
JavaScript定时器制作弹窗小广告
Feb 05 Javascript
AngularJS路由切换实现方法分析
Mar 17 Javascript
Node.js 8 中的重要新特性
Jun 28 Javascript
BootStrap Fileinput上传插件使用实例代码
Jul 28 Javascript
React Native悬浮按钮组件的示例代码
Apr 05 Javascript
js验证身份证号码记录的方法
Apr 26 Javascript
js canvas实现5张图片合成一张图片
Jul 15 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 #Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
Apr 13 #Javascript
JQuery 两种方法解决刚创建的元素遍历不到的问题
Apr 13 #Javascript
更高效的使用JQuery 这里总结了8个小技巧
Apr 13 #Javascript
深入理解关于javascript中apply()和call()方法的区别
Apr 12 #Javascript
javascript中去除数组重复元素的实现方法【实例】
Apr 12 #Javascript
Bootstrap每天必学之折叠
Apr 12 #Javascript
You might like
PHP的一个完整SMTP类(解决邮件服务器需要验证时的问题)
2006/10/09 PHP
PHP截取汉字乱码问题解决方法mb_substr函数的应用
2008/03/30 PHP
MYSQL 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
缓动函数requestAnimationFrame 更好的实现浏览器经动画
2012/12/07 Javascript
jQuery弹性滑动导航菜单实现思路及代码
2013/05/02 Javascript
jquery选择器排除某个DOM元素的方法(实例演示)
2014/04/25 Javascript
checkbox 选中一个另一个checkbox也会选中的实现代码
2016/07/09 Javascript
bootstrap组件之按钮式下拉菜单小结
2017/01/19 Javascript
简单的vue-resourse获取json并应用到模板示例
2017/02/10 Javascript
详解bootstrap导航栏.nav与.navbar区别
2017/11/23 Javascript
vue配置多页面的实现方法
2018/05/22 Javascript
js实现每日签到功能
2018/11/29 Javascript
vue自动化路由的实现代码
2019/09/30 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
Python 3中print函数的使用方法总结
2017/08/08 Python
Python操作MySQL数据库的三种方法总结
2018/01/30 Python
Python装饰器知识点补充
2018/05/28 Python
python 返回列表中某个值的索引方法
2018/11/07 Python
Django model update的多种用法介绍
2020/03/28 Python
基于torch.where和布尔索引的速度比较
2020/01/02 Python
Python基于execjs运行js过程解析
2020/11/27 Python
基于CSS3 animation动画属性实现轮播图效果
2017/09/12 HTML / CSS
html5开发三八女王节表白神器
2018/03/07 HTML / CSS
Spartoo比利时:欧洲时尚购物网站
2017/12/06 全球购物
Java如何调用外部Exe程序
2015/07/04 面试题
机械专业个人求职自荐信格式
2013/09/21 职场文书
我未来的职业规划范文
2014/01/11 职场文书
服务员岗位职责
2014/01/29 职场文书
小学家长评语大全
2014/04/16 职场文书
应收账款管理制度
2015/08/06 职场文书
小学生作文之《压岁钱的烦恼》
2019/09/27 职场文书
总结Python连接CS2000的详细步骤
2021/06/23 Python
VS2019连接MySQL数据库的过程及常见问题总结
2021/11/27 MySQL
JS函数式编程实现XDM一
2022/06/16 Javascript
win10怎么设置右下角图标不折叠?Win10设置右下角图标不折叠的方法
2022/07/15 数码科技