自定义滚动条:兼容主流浏览器以及IE8+

mCustomScrollbar.js(依赖jQuery、jquery-mousewheel):兼容主流浏览器和IE,但是在ie8上滚动比较不顺畅。

本文采用zUi;如下包括源码和demo,兼容性测试通过。

zUI.js (依赖于jQuery)

外层元素定高,overflow:hidden;内层元素长度自然撑开。对外层元素使用zui的方法panel();

(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);
	

具体实现:

<!DOCTYPE HTML>
<html>
<head>
	<title>panel</title>
	<meta charset="utf-8">
	<script src="http://www.jq22.com/jquery/1.11.1/jquery.min.js"></script>
	<script type="text/javascript" src="zUI.js"></script>
	<style>
	body{ background-color:#252525}
		#demo{ width: 500px; height: 300px; border: 2px solid #1F1F1F; margin: 20px auto; overflow: hidden; 		}
		.box{
			height:300px;
			width:500px;
		}
		.zUIpanelScrollBox,.zUIpanelScrollBar{
			width:10px;
			top:4px;
			right:2px;
			border-radius:5px;
		
			
		}
		.zUIpanelScrollBox{
			background:black;opacity:0.1;
			filter:alpha(opacity=10);
		}
		.zUIpanelScrollBar{
			background:red;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:#546B8B">滚动条在这里</div>
			<div class="box" style="background:#5ACDE5">2</div>
			<div class="box" style="background:#483362">3</div>
			<div class="box" style="background:#723E4B">4</div>
			<div class="box" style="background:#546B8B">5</div>
		</div>
	</div>
</body>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值