自定义滚动条:兼容主流浏览器以及IE8+
2018-03-23 16:19
597 查看
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;
ba05
}
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>
相关文章推荐
- 完美兼容IE_Opera_Firefox等主流浏览器的锁定表格的 表头以及表头列
- 自定义浏览器滚动条的样式,打造属于你的滚动条风格——兼容IE和webkit(ff不支持)
- 自定义浏览器滚动条的样式,打造属于你的滚动条风格——兼容IE和webkit(ff不支持)
- 自定义滚动条支持滚轮——主流浏览器全兼容
- 【转】图片上传简单JS预览,兼容IE火狐等主流浏览器
- 上传图片带预览功能兼容IE和火狐等主流浏览器
- js阻止浏览器的默认行为以及停止事件冒泡(用JQuery实现回车提交,兼容IE、FF浏览器)
- 关闭浏览器输入框自动补齐 兼容IE,FF,Chrome等主流浏览器
- Js脚本:动态添加HTML自定义属性以及处理html元素的自定义属性(兼容Firefox和IE)
- js 打印DIV内容 print div 兼容IE FF Google等主流浏览器
- checkbox兼容主流浏览器的自定义样式
- js获取滚动条距离浏览器顶部,底部的高度,兼容ie和firefox
- Js 日期选择,可以的一个页面中重复使用本JS日历,兼容IE及火狐等主流浏览器,而且界面简洁、美观,操作体验也不错。
- js获得指定控件输入光标的坐标兼容IE,Chrome,火狐等多种主流浏览器
- jquery下拉菜单效果(超简洁实用,兼容IE和firefox等主流浏览器)
- javascript之自定义js封装库兼容主流浏览器实现DOM加载之后,页面完全加载之前执行js
- JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
- js阻止浏览器的默认行为以及停止事件冒泡(用JQuery实现回车提交,兼容IE、FF浏览器)
- JSP中用回车监听按钮事件兼容火狐 IE等主流浏览器
- 还是浏览器兼容——IE的盒子模型的宽高包含了滚动条没有