这介个的源码有吗,很多地方法没有太明白!!!
https://github.com/liuzhaoxu1996/slider-plugin
第一个排版乱了,js代码可以贴后面的。
var Scroll = {}; (function (win,doc,$) { function CusScrollBar(options) { if (this instanceof CusScrollBar) { this.init(options); } else { return CusScrollBar(options); } } $.extend(CusScrollBar.prototype, { init: function (options) { var _this = this; _this.options = { scrollDirection: "y", contentSelector: "", barSelector: "", sliderSelector: "", tabItemSelector: ".item", tabActive: "active", anchorSelector: ".anchor", correctSelector: ".correct-bot", articleSelector: ".article-text", wheelStep: 10 } $.extend(true,_this.options, options || {}); _this.initEvent(); return _this; }, initEvent: function () { var opts = this.options; this.cont = $(opts.contentSelector); this.slider = $(opts.sliderSelector); this.bar = opts.barSelector ? $(opts.barSelector) : _this.slider.parent(); this.tabItem = $(opts.tabItemSelector); this.anchor = $(opts.anchorSelector); this.correct = $(opts.correctSelector); this.article = $(opts.articleSelector); this.doc = $(doc); this.initSliderDrag().bindContentScroll().bindMouseWheel().initTabEvent().initArticleHeight(); }, initTabEvent: function () { // 监听标签事件 var _this = this; this.tabItem.on("click",function (e) { e.preventDefault(); var index = $(this).index(); _this.changeTabSelect(index); // 标签切换 _this.scrollTo(_this.cont[0].scrollTop + _this.getAnchorPosition(index)); // 内容跳转到锚点 }) return _this; }, initArticleHeight: function () { var _this = this, lastArticle = this.article.last(), lastArticleHeight = lastArticle.height(), contentHeight = _this.cont.height(); if (lastArticleHeight < contentHeight) { _this.correct[0].style.height = contentHeight - lastArticleHeight - _this.anchor.outerHeight() + "px"; } return _this; }, initSliderDrag: function () { // 滑块拖动功能 var _this = this, slider = this.slider, sliderEl = slider[0]; if (sliderEl) { var doc = this.doc, dragStartPagePosition, dragStartScrollPosition, dragContBarRate; function fnMove(e) { e.preventDefault(); if (dragStartPagePosition == null) { return; } // 内容滑动距离 = 滑块移动距离 * 比率 + 内容开始卷曲的高度 // 滑块移动距离 = 鼠标释放的位置 - 鼠标开始的位置 var scrollRange = dragStartScrollPosition + (e.pageY - dragStartPagePosition) * dragContBarRate; _this.scrollTo(scrollRange); } slider.on("mousedown",function (e) { e.preventDefault(); dragStartPagePosition = e.pageY; dragStartScrollPosition = _this.cont[0].scrollTop; dragContBarRate = _this.getMaxScrollRange() / _this.getMaxSliderRange(); // 滚动比率 = 内容可滚动高度 / 滑块可移动距离 doc.on("mousemove.scroll",function (e) { fnMove(e) }).on("mouseup.scroll",function () { doc.off("mousemove.scroll mouseup.scroll"); }); }); return _this; } }, changeTabSelect: function (index) { // 标签切换时变更自身元素和同胞元素的类名 var _this = this, active = _this.options.tabActive; return _this.tabItem.eq(index).addClass(active).siblings().removeClass(active); }, getAnchorPosition: function (index) { // 指定的锚点相对于可视区位置 var result = this.anchor.eq(index).position().top; return result; }, getAllAnchorPosition: function () { // 获得所有锚点位置 var _this = this, arrPosition = []; // 正序开始 for (var i = 0; i < _this.anchor.length; i++) { arrPosition.push(_this.cont[0].scrollTop + _this.getAnchorPosition(i)); } return arrPosition; }, bindContentScroll: function () { // 监听内容滚动,同步滑块位置 var _this = this; _this.cont.on("scroll",function () { var sliderEl = _this.slider && _this.slider[0]; // 如果两个都为object对象就返回第二个对象(第一个为jquery对象,第二个为DOM对象) if (sliderEl) { sliderEl.style.top = _this.getSliderPosition() + "px"; } }) return _this; }, getSliderPosition: function () { // 计算滑块当前位置 var _this = this, maxSliderPosition = _this.getMaxSliderRange(); // 滑块移动距离 = 滑块可移动距离 * 内容滚动高度 / 内容可滚动高度 var result = Math.min(maxSliderPosition, maxSliderPosition * _this.cont[0].scrollTop / _this.getMaxScrollRange()); return result; }, bindMouseWheel: function () { // 鼠标滚轮事件程序 var _this = this; // chrome支持mousewheel 属性取值120的倍数 正值表示向上 // Firefox支持DOMMouseScroll 属性取值3的倍数 负值表示向上 _this.cont.on("mousewheel DOMMouseScroll",function (e) { e.preventDefault(); // $.event.originalEvent 指向原生事件 var oEV = e.originalEvent, wheelRange = oEV.wheelDelta ? -oEV.wheelDelta / 120 : (oEV.detail || 0) / 3; _this.scrollTo(_this.cont[0].scrollTop + wheelRange * _this.options.wheelStep); }); return _this; }, getMaxScrollRange: function () { // 内容可滚动高度 var _this = this; var result = Math.max(_this.cont.height(), _this.cont[0].scrollHeight) - _this.cont.height(); return result; }, getMaxSliderRange: function () { // 滑块可滚动距离 var _this = this; var result = _this.bar.height() - _this.slider.height(); return result; }, scrollTo: function (positionValue) { // 内容移动程序 var _this = this, arrPosition = this.getAllAnchorPosition(); // 滚动条位置与tab标签对应关系 function getIndex(positionValue) { var index = 0; // 正序开始 // 当scrolltop的值大于锚点定位的位置,则表示内容在那个锚点范围里面 for (var i = 0; i < arrPosition.length; i++) { if (positionValue >= arrPosition[i]) { index = i; }; } return index; } // 锚点数和标签数相同 if (arrPosition.length === _this.tabItem.length) { // 标签选择事件 _this.changeTabSelect(getIndex(positionValue)); } _this.cont.scrollTop(positionValue); } }); Scroll.CusScrollBar = CusScrollBar; })(window,document,jQuery); new Scroll.CusScrollBar({ contentSelector: ".content", barSelector: ".scroll-bar", sliderSelector: ".scroll-slider" });
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义滚动条</title> <style> body,ul,li,div,h3,p{margin: 0; padding: 0;} body{background-color: #ccc;} li{list-style: none;} .clx{*zoom: 1;} .clx:after{content: ""; display: table; clear: both;} .wrap{position: relative; width: 540px; margin: 30px auto; border: 1px solid #A489F1; background-color: #fff;} .tab{height: 34px; color: #666; background-color: #f8f8f8;} .tab .item{float: left; height: 32px; padding: 0 20px; font-size: 14px; line-height: 34px; text-align: center; border: 1px solid #e5e5e5;} .tab .active{margin: -1px 0; color: #00be3c; background-color: #fff; border-top: 2px solid #00be3c;} .main{width: 100%; height: 300px;} .main .content{position: relative; height: 100%; padding: 0 15px; overflow: hidden;} .main .content .anchor{font: 16px/3 "Microsoft Yahei"; text-align: center;} .main .content .article-text p{font-size: 14px; line-height: 20px; text-indent: 2rem; margin-bottom: 10px;} .scroll-bar{position: absolute; top: 0; right: 0; width: 10px; height: 100%; background-color: #eaeaea;} .scroll-bar .scroll-slider{position: absolute; top: 0; left: 1px; width: 8px; height: 30px; background-color: #fff;} </style> </head> <body> <div> <ul class="tab clx"> <li class="item active">第一篇</li> <li>第二篇</li> <li>第三篇</li> <li>第四篇</li> </ul> <div> <div> <h3>绿色的春</h3> <div> <p>春的百花齐放,夏的骄阳似火,秋的硕果累累,冬的白雪皑皑,无一不成为别致的风景。勤劳、智慧而又知道享受的人们,学会了春耕夏种,秋收冬藏。知道了在春天种下希望,在夏天吹一习凉风,在秋天赏一轮月,在冬天升一炉火。</p> <p>当四季轮回更替时,人们的心绪便也随之折折叠叠。春恨秋悲,春愁夏伤皆因四季而起。一滴春雨,一片残荷,一夜秋风,一朵雪花都足以让心情变得敏感而丰富。人们在春中体会到了温暖,在夏中感受到了火热,在秋里寻找到了悲凉,在冬中懂得了残酷。</p> <p>春缠绵,夏热情,秋悲凉,冬庄严。每一个季节都象一首歌,在万物面前心情地展示它的弦律,让生灵情不自禁随之翩翩起舞。没有最好的时节,也没有最坏的时节。诚如天门慧开禅师的偈语所言:春有百花秋有月,夏有凉风冬有雪。若无闲事挂心头,便是人间好时节。</p> <p>当气温不再寒冷,当风雪不再肆虐,当春雷惊醒沉睡的大地,当种子舒展他慵懒的双臂,当枯枝抽出新芽,当燕子开始低语,当浅绿的颜色逼进眼帘,当鲜花展开迷人的笑靥……,春已翩然而至。</p> <p>春,轻易地便让人联想到“青春”、“光明”、“希望”这些字眼。“一年之际在于春”。人们都满怀信心地在这个季节里,开始新的一年。农民开始盘算一年的生计,商人开始预计一年的经营,文人开始酝酿新的篇章,而学子则准备着新的学业。</p> <p>逃离了冬的严寒,避开了夏的酷热,也没有了秋的萧瑟,春,这个季节,始终是不愠不火的,宛如一个温柔娴静的女子。偶尔的几场春雨,亦无不带来令人欣喜的清新与潮湿。于是有人说:“春雨贵如油”、“春光无限好”。为了充分领略这无限春光,在工作之余,人们常常会想到春游,去亲近大自然,让疲惫的身心在美好的春光中适意休憩。</p> <p>春天的时光也是短暂的。也许你还没有来得及好好感受春的气息,也许你还没有来得及实践你在春的规划,夏已“呼啸”而至。</p> <p>春就是这样,来无声,去无影。</p> </div> <h3>红色的夏</h3> <div> <p>夏的登场,绝不会毫无声息。</p> <p>夏会在清晨将阳光早早地送到千家万户,抽去人们身上懒惰的因子;夏会让蝉发出响亮的长鸣,让蛙演奏夜晚的交响曲;夏会让荷吐露沁人的芬芳,让树木尽显婀娜的身姿。</p> <p>灼热的阳光,倾盆的大雨,吝啬的风成了夏的招牌。</p> <p>夏若不是一位被娇宠的孩儿,就必定是一位热血方刚的青年。“豪爽”而“干脆”一直是夏的风格。要晴就晴它个晴空万里,要下雨就下它个酣畅淋漓。夏天的阳光,绝没有春的柔和,一缕缕都带着穿透力,似乎要把万物烤焦。夏天的雨,也绝没有春的缠绵,每一滴雨点似乎都要显示它的“份量”,一个个都掷地有声。夏天的风,轻易不来,来也是一丝丝的,有时还带着炎热的气息。</p> <p>夏日里的人们,有着饱满的激情和火样的热情。通常都是早早地起床,却迟迟不肯歇息。他们工作、学习都鼓足了干劲,似乎要把一年的规划放在这一季完成。夜晚,娱乐场所、夜宵摊边、公园角落也凭空地多了许多男男女女的身影。</p> <p>在酷热的夏季里,人们都喜欢的活动,当是游泳了。让清凉的水浸润发烫的肌肤,在水里游弋时,感觉自己成了一条自由自在的鱼。</p> <p>时光飞逝。或许你还在畏惧夏的炎热,或许你还在留恋水的温柔,而秋风乍起时,不觉又过了一季。</p> </div> <h3>黄色的秋</h3> <div> <p>“春种一粒粟,秋收万颗籽”。秋,是收获的季节。春天里辛勤的耕种,在秋天有了丰硕的成果。看看金黄的麦浪和累累的硕果,于是农人的眼里,便有了满意的欣喜。</p> <p>秋,是团圆的季节。嫦娥奔月的古老传说和中秋的习俗,使得华夏的儿女都记得在八月十五那一天,捧着圆圆的月饼,对着皎洁的月亮,尽量和家人一起团聚。</p> <p>秋,是思念的季节。悬挂在天空的那一轮月,最能勾起游子对故乡的思念。“床前明月光,疑是地上霜,举头望明月,低头思故乡。”李白将那种思念汇成了这首老少皆知的诗篇。</p> <p>秋,也是伤感的季节。秋风的呜咽,秋雨的凄迷,飘零的黄叶,飞舞的落花……,无一不牵动文人墨客敏感的心。看秋风萧瑟,听秋雨凄凄,那位有名的词人柳永说:“多情自古伤离别,更哪堪,冷落清秋节。”看台空院废,落花满地,郑如英写道:“台空院废人依旧,月沉云淡花羞。芙蓉寂寞小亭秋,黄花伤晚落,相对倍添愁”。秋,会在无意间将离愁别绪植入多愁善感的人的心里。</p> <p>但,大自然自有它固定的规律和节奏。你欣喜也罢,伤感也罢,秋,总以它不变的步伐,轻盈地走过。只剩下或许茫然无措的你,在独自回味。</p> </div> <h3>白色的冬</h3> <div> <p>冬日的阳光,是那样热切地被人期盼。尽管气温未必因它的出现而上升太多,但当那丝丝光芒照耀大地时,温暖的感觉便自心底升起。</p> <p>人们习惯在每个寒冷的日子里,渴望久违的天晴;在每一个冬季期待春暖花开。</p> </div> <div></div> </div> <div> <div></div> </div> </div> </div> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript"> var Scroll = {}; (function (win,doc,$) { function CusScrollBar(options) { if (this instanceof CusScrollBar) { this.init(options); } else { return CusScrollBar(options); } } $.extend(CusScrollBar.prototype, { init: function (options) { var _this = this; _this.options = { scrollDirection: "y", contentSelector: "", barSelector: "", sliderSelector: "", tabItemSelector: ".item", tabActive: "active", anchorSelector: ".anchor", correctSelector: ".correct-bot", articleSelector: ".article-text", wheelStep: 10 } $.extend(true,_this.options, options || {}); _this.initEvent(); return _this; }, initEvent: function () { var opts = this.options; this.cont = $(opts.contentSelector); this.slider = $(opts.sliderSelector); this.bar = opts.barSelector ? $(opts.barSelector) : _this.slider.parent(); this.tabItem = $(opts.tabItemSelector); this.anchor = $(opts.anchorSelector); this.correct = $(opts.correctSelector); this.article = $(opts.articleSelector); this.doc = $(doc); this.initSliderDrag().bindContentScroll().bindMouseWheel().initTabEvent().initArticleHeight(); }, initTabEvent: function () { // 监听标签事件 var _this = this; this.tabItem.on("click",function (e) { e.preventDefault(); var index = $(this).index(); _this.changeTabSelect(index); // 标签切换 _this.scrollTo(_this.cont[0].scrollTop + _this.getAnchorPosition(index)); // 内容跳转到锚点 }) return _this; }, initArticleHeight: function () { var _this = this, lastArticle = this.article.last(), lastArticleHeight = lastArticle.height(), contentHeight = _this.cont.height(); if (lastArticleHeight < contentHeight) { _this.correct[0].style.height = contentHeight - lastArticleHeight - _this.anchor.outerHeight() + "px"; } return _this; }, initSliderDrag: function () { // 滑块拖动功能 var _this = this, slider = this.slider, sliderEl = slider[0]; if (sliderEl) { var doc = this.doc, dragStartPagePosition, dragStartScrollPosition, dragContBarRate; function fnMove(e) { e.preventDefault(); if (dragStartPagePosition == null) { return; } // 内容滑动距离 = 滑块移动距离 * 比率 + 内容开始卷曲的高度 // 滑块移动距离 = 鼠标释放的位置 - 鼠标开始的位置 var scrollRange = dragStartScrollPosition + (e.pageY - dragStartPagePosition) * dragContBarRate; _this.scrollTo(scrollRange); } slider.on("mousedown",function (e) { e.preventDefault(); dragStartPagePosition = e.pageY; dragStartScrollPosition = _this.cont[0].scrollTop; dragContBarRate = _this.getMaxScrollRange() / _this.getMaxSliderRange(); // 滚动比率 = 内容可滚动高度 / 滑块可移动距离 doc.on("mousemove.scroll",function (e) { fnMove(e) }).on("mouseup.scroll",function () { doc.off("mousemove.scroll mouseup.scroll"); }); }); return _this; } }, changeTabSelect: function (index) { // 标签切换时变更自身元素和同胞元素的类名 var _this = this, active = _this.options.tabActive; return _this.tabItem.eq(index).addClass(active).siblings().removeClass(active); }, getAnchorPosition: function (index) { // 指定的锚点相对于可视区位置 var result = this.anchor.eq(index).position().top; return result; }, getAllAnchorPosition: function () { // 获得所有锚点位置 var _this = this, arrPosition = []; // 正序开始 for (var i = 0; i < _this.anchor.length; i++) { arrPosition.push(_this.cont[0].scrollTop + _this.getAnchorPosition(i)); } return arrPosition; }, bindContentScroll: function () { // 监听内容滚动,同步滑块位置 var _this = this; _this.cont.on("scroll",function () { var sliderEl = _this.slider && _this.slider[0]; // 如果两个都为object对象就返回第二个对象(第一个为jquery对象,第二个为DOM对象) if (sliderEl) { sliderEl.style.top = _this.getSliderPosition() + "px"; } }) return _this; }, getSliderPosition: function () { // 计算滑块当前位置 var _this = this, maxSliderPosition = _this.getMaxSliderRange(); // 滑块移动距离 = 滑块可移动距离 * 内容滚动高度 / 内容可滚动高度 var result = Math.min(maxSliderPosition, maxSliderPosition * _this.cont[0].scrollTop / _this.getMaxScrollRange()); return result; }, bindMouseWheel: function () { // 鼠标滚轮事件程序 var _this = this; // chrome支持mousewheel 属性取值120的倍数 正值表示向上 // Firefox支持DOMMouseScroll 属性取值3的倍数 负值表示向上 _this.cont.on("mousewheel DOMMouseScroll",function (e) { e.preventDefault(); // $.event.originalEvent 指向原生事件 var oEV = e.originalEvent, wheelRange = oEV.wheelDelta ? -oEV.wheelDelta / 120 : (oEV.detail || 0) / 3; _this.scrollTo(_this.cont[0].scrollTop + wheelRange * _this.options.wheelStep); }); return _this; }, getMaxScrollRange: function () { // 内容可滚动高度 var _this = this; var result = Math.max(_this.cont.height(), _this.cont[0].scrollHeight) - _this.cont.height(); return result; }, getMaxSliderRange: function () { // 滑块可滚动距离 var _this = this; var result = _this.bar.height() - _this.slider.height(); return result; }, scrollTo: function (positionValue) { // 内容移动程序 var _this = this, arrPosition = this.getAllAnchorPosition(); // 滚动条位置与tab标签对应关系 function getIndex(positionValue) { var index = 0; // 正序开始 // 当scrolltop的值大于锚点定位的位置,则表示内容在那个锚点范围里面 for (var i = 0; i < arrPosition.length; i++) { if (positionValue >= arrPosition[i]) { index = i; }; } return index; } // 锚点数和标签数相同 if (arrPosition.length === _this.tabItem.length) { // 标签选择事件 _this.changeTabSelect(getIndex(positionValue)); } _this.cont.scrollTop(positionValue); } }); Scroll.CusScrollBar = CusScrollBar; })(window,document,jQuery); new Scroll.CusScrollBar({ contentSelector: ".content", barSelector: ".scroll-bar", sliderSelector: ".scroll-slider" }); </script> </body> </html>