自定义滚动条:兼容主流浏览器以及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 = $("
"); jqScrollBox.addClass(opts.sBoxClassName); //创建滚动条 var jqScrollBar = $("
"); 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);

具体实现:




	panel
	
	
	
	
	


	
滚动条在这里
2
3
4
5


你可能感兴趣的:(css)