自定义滚动条

<!DOCTYPE HTML>
<html>
<head>
<title>自定义滚动条</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="reset.css" type="text/css" />
<script type="text/javascript" src="js/jquery-1.11.2.min.js">    </script>
<script type="text/javascript">
(function($){
    $.zUI = $.zUI || {}
    $.zUI.emptyFn = function(){};
    $.zUI.asWidget = [];
    /*
     * core代码,定义增加一个插件的骨架
     */
    $.zUI.addWidget = function(sName,oSefDef){
        //设置规范中的常量sFlagName、sEventName、sOptsName
        $.zUI.asWidget.push(sName);
        var w = $.zUI[sName] = $.zUI[sName] || {};
        var sPrefix = "zUI" + sName
        w.sFlagName = sPrefix;
        w.sEventName = sPrefix + "Event";
        w.sOptsName = sPrefix + "Opts";
        w.__creator = $.zUI.emptyFn;
        w.__destroyer = $.zUI.emptyFn;
        $.extend(w,oSefDef);
        w.fn = function(ele,opts){
            var jqEle = $(ele);
            jqEle.data(w.sOptsName,$.extend({},w.defaults,opts));
            //如果该元素已经执行过了该插件,直接返回,仅相当于修改了配置参数
            if(jqEle.data(w.sFlagName)){
                return;
            }
            jqEle.data(w.sFlagName,true);
            w.__creator(ele);
            jqEle.on(jqEle.data(w.sEventName));
        };
        w.unfn = function(ele){
            w.__destroyer(ele);
            var jqEle = $(ele);//移除监听事件
            if(jqEle.data(w.sFlagName)){
                jqEle.off(jqEle.data(w.sEventName));
                jqEle.data(w.sFlagName,false);
            }
        }
        
    }
    /*
     * draggable
     * 参数:obj{
     * bOffsetParentBoundary:是否以定位父亲元素为边界,
     * oBoundary:指定元素left和top的边界值,形如{iMinLeft:...,iMaxLeft:...,iMinTop:...,iMaxTop:...},与上一个参数互斥
     * fnComputePosition:扩展函数,返回形如{left:...,top:...}的对象
     * }
     * 支持的自定义事件:
     * "draggable.start":drag起始,就是鼠标down后触发
     * "draggable.move":drag过程中多次触发
     * "draggable.stop":drag结束触发,就是鼠标up后触发
     */
    //注册draggable组件
    $.zUI.addWidget("draggable",{
        defaults:{
            bOffsetParentBoundary:false,//是否以定位父亲元素为边界
            oBoundary:null,//边界
            fnComputePosition:null//计算位置的函数
        },
        __creator:function(ele){
            var jqEle = $(ele);
            jqEle.data($.zUI.draggable.sEventName,{
            mousedown:function(ev){
            var jqThis = $(this);
            var opts = jqThis.data($.zUI.draggable.sOptsName);
            
            jqThis.trigger("draggable.start");
            var iOffsetX = ev.pageX - this.offsetLeft;
            var iOffsetY = ev.pageY - this.offsetTop;
            
            function fnMouseMove (ev) {
                var oPos = {};
                if(opts.fnComputePosition){
                    oPos = opts.fnComputePosition(ev,iOffsetX,iOffsetY);
                }else{
                    oPos.iLeft = ev.pageX - iOffsetX;
                    oPos.iTop = ev.pageY - iOffsetY;
                }
                
                var oBoundary = opts.oBoundary;
                if(opts.bOffsetParentBoundary){//如果以offsetParent作为边界
                    var eParent = jqThis.offsetParent()[0];
                    oBoundary = {};
                    oBoundary.iMinLeft = 0;
                    oBoundary.iMinTop = 0;
                    oBoundary.iMaxLeft = eParent.clientWidth - jqThis.outerWidth();
                    oBoundary.iMaxTop = eParent.clientHeight - jqThis.outerHeight();
                }
            
                if(oBoundary){//如果存在oBoundary,将oBoundary作为边界
                    oPos.iLeft = oPos.iLeft < oBoundary.iMinLeft ? oBoundary.iMinLeft : oPos.iLeft;
                    oPos.iLeft = oPos.iLeft > oBoundary.iMaxLeft ? oBoundary.iMaxLeft : oPos.iLeft;
                    oPos.iTop = oPos.iTop < oBoundary.iMinTop ? oBoundary.iMinTop : oPos.iTop;
                    oPos.iTop = oPos.iTop > oBoundary.iMaxTop ? oBoundary.iMaxTop : oPos.iTop;
                }
                
                jqThis.css({left:oPos.iLeft,top:oPos.iTop});
                ev.preventDefault();
                jqThis.trigger("draggable.move");
            }
            
            var oEvent = {
                mousemove:fnMouseMove,
                mouseup:function(){
                    $(document).off(oEvent);
                    jqThis.trigger("draggable.stop");
                }
            };
            
            $(document).on(oEvent);
        }});
        }
    });
    /*
     * panel
     * 参数:obj{
     *     iWheelStep:鼠标滑轮滚动时步进长度
     *    sBoxClassName:滚动框的样式
     *     sBarClassName:滚动条的样式
     * }
     */
    $.zUI.addWidget("panel",{
        defaults : {
                iWheelStep:16,
                sBoxClassName:"zUIpanelScrollBox",
                sBarClassName:"zUIpanelScrollBar"
        },
        __creator:function(ele){
            var jqThis = $(ele);
            //如果是static定位,加上relative定位
            if(jqThis.css("position") === "static"){
                jqThis.css("position","relative");
            }
            jqThis.css("overflow","hidden");
            
            //必须有一个唯一的直接子元素,给直接子元素加上绝对定位
            var jqChild = jqThis.children(":first");
            if(jqChild.length){
                jqChild.css({top:0,position:"absolute"});
            }else{
                return;
            }
            
            var opts = jqThis.data($.zUI.panel.sOptsName);
            //创建滚动框
            var jqScrollBox = $("<div style=‘position:absolute;display:none;line-height:0;‘></div>");
            jqScrollBox.addClass(opts.sBoxClassName);
            //创建滚动条
            var jqScrollBar= $("<div style=‘position:absolute;display:none;line-height:0;‘></div>");
            jqScrollBar.addClass(opts.sBarClassName);
            jqScrollBox.appendTo(jqThis);
            jqScrollBar.appendTo(jqThis);
            
            opts.iTop = parseInt(jqScrollBox.css("top"));
            opts.iWidth = jqScrollBar.width();
            opts.iRight = parseInt(jqScrollBox.css("right"));
            
    
            //添加拖拽触发自定义函数
            jqScrollBar.on("draggable.move",function(){
                var opts = jqThis.data($.zUI.panel.sOptsName);
                fnScrollContent(jqScrollBox,jqScrollBar,jqThis,jqChild,opts.iTop,0);
            });
            
          //事件对象
            var oEvent ={
                mouseenter:function(){
                    fnFreshScroll();
                    jqScrollBox.css("display","block");
                    jqScrollBar.css("display","block");
                },
                mouseleave:function(){
                    jqScrollBox.css("display","none");
                    jqScrollBar.css("display","none");
                }
            };
            
            var sMouseWheel = "mousewheel";
            if(!("onmousewheel" in document)){
                sMouseWheel = "DOMMouseScroll";
            }
            oEvent[sMouseWheel] = function(ev){
                var opts = jqThis.data($.zUI.panel.sOptsName);
                var iWheelDelta = 1;
                ev.preventDefault();//阻止默认事件
                ev = ev.originalEvent;//获取原生的event
                if(ev.wheelDelta){
                        iWheelDelta = ev.wheelDelta/120;
                }else{
                        iWheelDelta = -ev.detail/3;
                }
                var iMinTop = jqThis.innerHeight() - jqChild.outerHeight();
                //外面比里面高,不需要响应滚动
                if(iMinTop>0){
                    jqChild.css("top",0);
                    return;
                }
                var iTop = parseInt(jqChild.css("top"));
                var iTop = iTop + opts.iWheelStep*iWheelDelta;
                iTop = iTop > 0 ? 0 : iTop;
                iTop = iTop < iMinTop ? iMinTop : iTop;
                jqChild.css("top",iTop);
                fnScrollContent(jqThis,jqChild,jqScrollBox,jqScrollBar,0,opts.iTop);
            }
            //记录添加事件
            jqThis.data($.zUI.panel.sEventName,oEvent);
            //跟随滚动函数
            function fnScrollContent(jqWrapper,jqContent,jqFollowWrapper,jqFlollowContent,iOffset1,iOffset2){
                var opts = jqThis.data($.zUI.panel.sOptsName);
                var rate = (parseInt(jqContent.css("top"))-iOffset1)/(jqContent.outerHeight()-jqWrapper.innerHeight())//卷起的比率
                var iTop = (jqFlollowContent.outerHeight()-jqFollowWrapper.innerHeight())*rate + iOffset2;
                jqFlollowContent.css("top",iTop);
            }
        
            //刷新滚动条
            function fnFreshScroll(){
    
                var opts = jqThis.data($.zUI.panel.sOptsName);
                var iScrollBoxHeight = jqThis.innerHeight()-2*opts.iTop;
                var iRate = jqThis.innerHeight()/jqChild.outerHeight();
                var iScrollBarHeight = iScrollBarHeight = Math.round(iRate*iScrollBoxHeight);
                //如果比率大于等于1,不需要滚动条,自然也不需要添加拖拽事件
                if(iRate >= 1){
                    jqScrollBox.css("height",0);
                    jqScrollBar.css("height",0);
                    return;
                }
                jqScrollBox.css("height",iScrollBoxHeight);
                jqScrollBar.css("height",iScrollBarHeight);
                //计算拖拽边界,添加拖拽事件
                var oBoundary = {iMinTop:opts.iTop};
                oBoundary.iMaxTop = iScrollBoxHeight - Math.round(iRate*iScrollBoxHeight)+opts.iTop;
                oBoundary.iMinLeft = jqThis.innerWidth() - opts.iWidth - opts.iRight;
                oBoundary.iMaxLeft = oBoundary.iMinLeft;
                fnScrollContent(jqThis,jqChild,jqScrollBox,jqScrollBar,0,opts.iTop);
                jqScrollBar.draggable({oBoundary:oBoundary});
            }
        },
            __destroyer:function(ele){
                var jqEle = $(ele);
                if(jqEle.data($.zUI.panel.sFlagName)){
                    var opts = jqEle.data($.zUI.panel.sOptsName);
                    jqEle.children("."+opts.sBoxClassName).remove();
                    jqEle.children("."+opts.sBarClassName).remove();
                }
        }
    });
    
    $.each($.zUI.asWidget,function(i,widget){
        unWidget = "un"+widget;
        var w = {};
        w[widget] = function(args){
                this.each(function(){
                $.zUI[widget].fn(this,args);
            });
            return this;
        };
        w[unWidget] = function(){
                this.each(function(){
                $.zUI[widget].unfn(this);
            });
            return this;
        }
        $.fn.extend(w);
    });
})(jQuery);
    
</script>
<style type="text/css">
    #demo{
        width:1000px;
        height:500px;
        border:10px solid gray;
        margin:20px auto;
        overflow:hidden;
        position:relative;
    }
    .box{
        height:500px;
        width:1000px;
    }
    .zUIpanelScrollBox,.zUIpanelScrollBar{
        width:10px;
        top:4px;
        right:2px;
        border-radius:5px;
        
    }
    .zUIpanelScrollBox{
        background:black;opacity:0.1;
        filter:alpha(opacity=10);
    }
    .zUIpanelScrollBar{
        background:#fff;opacity:0.8;
        filter:alpha(opacity=80);
    }
</style>
<script>
    $(function(){
        $("#demo").panel({iWheelStep:32});
    });
</script>
</head>
<body>
<div id="demo">
    <div>
        <div class="box" style="background:green"></div>
        <div class="box" style="background:pink"></div>
        <div class="box" style="background:yellow"></div>
        <div class="box" style="background:gray"></div>
        <div class="box" style="background:blue"></div>
    </div>
</div>
</body>
</html>

时间: 2024-08-01 22:20:08

自定义滚动条的相关文章

利用CSS3新特性实现完全兼容的自定义滚动条。

背景:最近项目里面因为统一页面风格,用到了自定义滚动条,在完成之前的那个滚动条的时候,与网上各个滚动条插件实现的方法类似,相当于造了轮子,通过css3的 网上看到的滚动条插件多数是通过监听内容的滚动事件,由于原生js的滚动事件存在一些bug,所以实际上用jQuery的mousewheel.js插件的比较多,自己做的滚动条也是引用了该插件. 首先说一说自定义滚动条实现的普遍步骤和方法: 背景: A需要滚动. 1.给A添加一个父级S包裹,并将B进行绝对或相对定位(这点根据S的定位,目的是为了保持原有

iPhone手机解锁效果&amp;&amp;自定义滚动条&amp;&amp;拖拽--Clone&amp;&amp;窗口拖拽(改变大小/最小化/最大化/还原/关闭)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

CSS自定义滚动条样式

相信很多人都遇到过在设计中自定义滚动条样式的情景,之前我都是努力说服设计师接受浏览器自带的滚动条样式,但是这样只能规避还是解决不了问题,最近在项目中遇到了,正好来总结一下.当然,兼容所有浏览器的滚动条样式目前是不存在的. IE下的滚动条样式 IE是最早提供滚动条的样式支持,好多年了,但是其它浏览器一直没有支持,IE独孤求败了. 这些样式规则很简单: scrollbar-arrow-color: color; /*三角箭头的颜色*/ scrollbar-face-color: color; /*立

移动端网页自定义滚动条

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta id="viewport" name="viewport" content="initial-scale=1.0,user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <title&

jQuery自定义滚动条样式插件mCustomScrollbar

如果你构建一个很有特色和创意的网页,那么肯定希望定义网页中的滚动条样式,这方面的 jQuery 插件比较不错的,有两个:jScrollPane 和 mCustomScrollbar. 关于 jScrollPane,大家见过的可能比较多,但是这个插件太过于古老而且功能不强大,效果在几年前非常不错,但是放在现在就不好说了.所以我选择了后者:mCustomScrollbar.下图是两者官方示例的简单对比: 本文就是介绍如何使用 mCustomScrollbar 这个插件,大部分的内容是翻译自 mCus

CSS3自定义滚动条样式

写在前面 滚动条是个很常见的东东,不过某些浏览器自带的滚动条确实不太好看啊,下面可以作为学习,探讨下自定义滚动条的实现,这样你的滚动条就可以美美的啦.但是,也只能玩玩,因为只针对webkit内核的浏览器啊啊啊啊啊! overflow介绍 定义:overflow 属性指定当它溢出其块级容器时,是否剪辑内容,渲染滚动条或显示内容. 属性值 overflow:visible //默认值.内容不会被修剪,超出内容会显示在元素框之外 overflow:hidden //内容会被修剪.超出内容被隐藏 ove

CSS3自定义滚动条样式 之 -webkit-scrollbar

有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 webkit支持拥有overflow属性的区域,列表框,下拉菜单,textarea的滚动条自定义样式,所以用处还是挺大的.当然,兼容所有浏览器的滚动条样式目前是不存在的. 演示 来看看这2个滚动条demo:demo1(图片版).demo2(纯CSS3版) 滚动条组成 ::-webkit-scroll

CSS3自定义滚动条样式 -webkit-scrollbar (一)

Webkit支持拥有overflow属性的区域,列表框,下拉菜单,textarea的滚动条自定义样式.当然,兼容所有浏览器的滚动条样式目前是不存在的. 滚动条的组成: ::-webkit-scrollbar         滚动条整体部分  ::-webkit-scrollbar-thumb             滚动条里面的小方块,能上下左右移动(取决于是垂直滚动条还是水平滚动条)  ::-webkit-scrollbar-track      滚动条的轨道(里面装有thumb)  ::-w

CSS3自定义滚动条样式 -webkit-scrollbar

http://blog.csdn.net/hanshileiai/article/details/40398177#t1 有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 webkit支持拥有overflow属性的区域,列表框,下拉菜单,textarea的滚动条自定义样式,所以用处还是挺大的.当然,兼容所有浏览器的滚动条样式目前是不存在的. 演示