js页面滚动时层智能浮动定位实现(jQuery/MooTools)

这篇文章发布于 2010年11月11日,星期四,20:44,归类于 JS实例。 阅读 170517 次, 今日 6 次 28 条评论

 

一、应用展示

关于层的智能浮动效果早在几年前我就在国外的一些个人网站的垂直导航上见到了,现在似乎在国内一些商业网站上也屡见此效果,例如淘宝网的搜索结果页的排序水平条,在默认状态下,滚动条跟随页面滚动,如下:
淘宝网搜索页排序水平条 张鑫旭-鑫空间-鑫生活

随着页面向下滚动,当此水平条接触浏览器的上边缘时,水平条独立出来,不跟随滚动条滚动了,如下图所示:
淘宝网搜索页水平条 张鑫旭-鑫空间-鑫生活

类似的效果在新浪微博上也有:
新浪微博上智能定位层 张鑫旭-鑫空间-鑫生活

当页面滚动,新动态提示开始要淡出浏览器窗口的时候,其浮动于浏览器窗口的最上沿显示,如下图所示:
新浪微博智能浮动层 张鑫旭-鑫空间-鑫生活

此效果实现原理其实很简单,本文就将展示其实现。

二、实现原理

默认状态就是默认状态,什么事情也不用做,定位是absolute也好,static也好,都ok。关键是当浏览器滚动的时候,对象(要浮动的层)要移除浏览器界面视区的时候,修改其position属性,让其浮动在窗口的上沿显示就可以了。最好的position属性就是fixed了,可以在IE6+和其他浏览器下浮动层平滑固定定位,由于IE6前辈不支持fixed属性,所以,后退一步,使用absolute属性代替,但是会有副作用——滚动不平滑。但,这也是没有办法的事情了。

现在关键就是如何判断当前层与浏览器窗口的上边缘接触呢?当浮动层与浏览器窗口上边缘接触的一瞬间,其页面垂直偏移值与页面的滚动高度其实是一致的,所以,用这个进行判断就OK了,但是,如何获得页面上元素距离页面的垂直距离呢?纯粹的js代码获得此值还是比较麻烦的,好在JavaScript库帮我们解决了这些工作,所以,我们的工作其实就很平坦,下面就将展示如何在jQuery库以及MooTools库下实现该效果。

三、jQuery下的层的智能浮动

方法代码如下:

$.fn.smartFloat = function() {
    var position = function(element) {
        var top = element.position().top, pos = element.css("position");
        $(window).scroll(function() {
            var scrolls = $(this).scrollTop();
            if (scrolls > top) {
                if (window.XMLHttpRequest) {
                    element.css({
                        position: "fixed",
                        top: 0
                    });    
                } else {
                    element.css({
                        top: scrolls
                    });    
                }
            }else {
                element.css({
                    position: "absolute",
                    top: top
                });    
            }
        });
    };
    return $(this).each(function() {
        position($(this));                         
    });
};

调用很简单,直接一行代码就ok了,例如下面:

$("#float").smartFloat();

妥妥儿的,就一小段绑定就实现了idfloat的标签有了智能浮动功能,效果描述就是:当id为float的元素在滚动的时候与浏览器上边缘接触时就不会再跟随滚动条滚动了。

您可以狠狠地点击这里:jQuery下的层的智能浮动demo

打开demo页面,您会看到右侧自诩羞涩的浮动层了,滚动页面观察效果:
jQuery智能浮动demo效果截图 张鑫旭-鑫空间-鑫生活

四、MooTools下的层的智能浮动

与jQuery实现一样,MooTools库下也已经将此方法包装了起来,代码如下:

var $smartFloat = function(elements) {
    var position = function(element) {
        var top = element.getPosition().y, pos = element.getStyle("position");
        window.addEvent("scroll", function() {
            var scrolls = this.getScroll().y;
            if (scrolls > top) {
                if (window.XMLHttpRequest) {
                    element.setStyles({
                        position: "fixed",
                        top: 0
                    });    
                } else {
                    element.setStyles({
                        top: scrolls
                    });    
                }
            }else {
                element.setStyles({
                    position: "absolute",
                    top: top
                });    
            }                       
        });
    };
    if ($type(elements) === "array") {
        return elements.each(function(items) {
            position(items);                         
        });
    } else if ($type(elements) === "element") {
        position(elements);    
    }
};

使用也是非常的简单,就一句代码,同样以id为float的标签举例,代码如下:

$smartFloat($("float"));

您可以狠狠地点击这里:MooTools下的层的智能浮动demo

滚动demo页面的滚动条,当“羞涩”的浮动层与浏览器边缘“接触”的时候,就不再跟随滚动条滚动了,如下图所示:
层的智能浮动demo页面 张鑫旭-鑫空间-鑫生活

五、光棍节结语

又是一年光棍节,巧的是今天也是德艺双馨的青少年启蒙教育家苍井空姐姐的生日。我想起了高中时的“棍子帮”,想起了“封棍”,“黄棍”;想起来了大学时候的“光棍协议”(藏在墙上我的画的后面)。今天我没有过节,而是听着悲催的音乐写着同样孤独气息的文章,不是因为我已经脱离“棍”的称号,而是看不到脱离“棍”称号的迹象。究其原因,或许正是因为在这个特殊的日子还宅在电脑前写东西而不是出去看看靓妹。罢了罢了,孤独是可以成就人的,聊以慰藉吧。

突然发现原来已经好久没有写效果实例了,悲催的时光正悄无声息地带走我年少的岁月,一晃数月已逝。当N年后再回过头来看这段时光是会觉得得到的多呢还是失去多呢?谁知道呢!

资质尚浅,方法仅供参考,或许有更好更简洁高效的实现方法,欢迎交流,欢迎指正。最后,祝同样单身的人们“光棍节快乐!” ——去淘宝5折狂shopping吧!

(本篇完)

分享到:


发表评论(目前28 条评论)

  1. asdfq说道:

    position:sticky 。

  2. 白吟说道:

    楼下说jquery demo没效果的,是因为页面引用的jquery地址是http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js被墙了,翻墙就能看了。
    ps.其实看代码就行了,实现效果文章里都讲的很清楚呀。

  3. fermos说道:

    怎么的,DEMO页面没有实现 效果哟???????

  4. kailiuwang.net说道:

    你好,很早就用了你上面那个代码。最近发现不能用了,代码不管用了,不知道是什么原因?麻烦看一看

  5. ice_liu说道:

    element.css({
    top: scrolls
    });
    这句是针对非IE浏览器吗,是什么意思,求大神解答

  6. window.XMLHttpRequest说道:

    楼主你好,这个demo我看懂了,但是有个小问题请教,window.XMLHttpRequest这句判断是判断什么呢,感觉不加也可以。

  7. 魅月痕说道:

    考虑到这个浮动元素可能被嵌套到别的元素里,加上一句更好:
    然后在浮动的时候综合考虑父元素的位置关系
    var ptop = element.parent().position().top;

    完整代码如下:
    $.fn.smartFloat = function() {
    var position = function(element) {
    var ptop = element.parent().position().top;
    var top = element.position().top;
    $(window).scroll(function() {
    var scrolls = $(this).scrollTop();
    if (scrolls > top+ptop) {
    if (window.XMLHttpRequest) {
    element.css({
    position: “fixed”,
    top: 0
    });
    } else {
    element.css({
    top: scrolls
    });
    }
    }else {
    element.css({
    position: “absolute”,
    top: top
    });
    }
    });
    };
    return $(this).each(function() {
    position($(this));
    });
    };

  8. zhyt说道:

    我用的你第一段jQuery的代码,当侧边栏到窗口顶端的时候,侧边栏自己变宽了,就是侧边栏的宽度自己顶到屏幕最右边了(我的页面两侧有空白),请问这是为什么呀?因为改了position的值?我试着在top:0下面加了一句width:250px,结果侧边栏又不能固定在窗口顶部了,请高手指点一二,甚为感激啊……

  9. Kevin说道:

    大神,mootools下怎么删除层啊?

  10. 海淘说道:

    1如果侧栏的长度大于内容的长度,那么就会破格。
    2有个BUG,浮动层比较大的话,例如用于地图显示,接触到底部版权信息部分会重叠。
    我是在左右两栏都不固定的情况下使用这个效果的,1的问题我能解决掉,可以实现右边比左边内容部分高的时候也能平衡 可是上面第二个问题我解决不了 如果浮动层比较高,直接挡住下面了

  11. 夜央说道:

    高手大大。我是wordpress搭建的个人博客。我把代码添加到主题的js当中了主题也加载jquery库啦。为什么实现不了呢?求助哈…

  12. 5不出来说道:

    顶 不过简单看着代码还不会运用 想弄个导航栏的 求指教

  13. 飞歌说道:

    很早就想做这种效果了,很好的实例,顶了

  14. bluehost优惠说道:

    这个看起来不错,正在找相关的资料.不错.

  15. mack说道:

    调用很简单,直接一行代码就ok了,”$(“#float”).smartFloat();”。请教下,我看不太懂,这个调用的代码是放在什么地方?调用时就直接这个代码?不要加些括号什么的吗?

  16. bolo说道:

    第三和第四种方法里都有个pos = element.getStyle(“position”),这是用来做什么的?

  17. AJ说道:

    有个BUG,浮动层比较大的话,例如用于地图显示,接触到底部版权信息部分会重叠。

  18. apple说道:

    好像和smarty不兼容

  19. 创意吧!说道:

    楼主你好,想请教窗口左边一个浮动按钮,点击一下弹出来淘宝搜索框,这个要怎么实现呢? 有插件吗? 有的话能给个链接吗?

  20. 蚊子说道:

    俺拿过来怎么不行呢,往指点一下谢谢

  21. 冰剑说道:

    还是有些问题。。。
    如果侧栏的长度大于内容的长度,那么就会破格。

  22. 康康说道:

    我喜欢看效果!

  23. crossyou说道:

    这个效果曾经写过,挺不错的。

  24. River说道:

    我们其实一直有她陪伴的,她就是——电脑。

  25. Mr.L说道:

    这个很不错