javascript自定義滾動(dòng)條實(shí)現(xiàn)代碼
在工作中經(jīng)常會(huì)遇到內(nèi)容會(huì)超出固定的一個(gè)范圍,超出的內(nèi)容一般會(huì)使用到滾動(dòng)條來滾動(dòng)顯示。
但是用瀏覽器默認(rèn)的滾動(dòng)條經(jīng)常被產(chǎn)品經(jīng)理鄙視,可是用css卻改變不了滾動(dòng)條的樣式,還好,有萬能的js ^_^~~
網(wǎng)上有各種各樣的插件,但最順手的還是自己寫的,還可以一邊擼一邊當(dāng)學(xué)習(xí),自己動(dòng)手豐衣足食 (*^__^*)
其中這三個(gè)問題深深地困擾我:
- 1、滾動(dòng)條高度
- 2、每次點(diǎn)擊向上、向下按鈕的時(shí)候滾動(dòng)條應(yīng)該移動(dòng)多少距離
- 3、每拖動(dòng)1px滾動(dòng)條,頁面需要移動(dòng)多少?
整個(gè)的框架大概是長(zhǎng)這樣的:

先來看看第一個(gè)問題。
由于目前已經(jīng)知道內(nèi)容區(qū)域的高度和內(nèi)容可視高度以及滾動(dòng)條可滾動(dòng)區(qū)域的高度了,由于內(nèi)容區(qū)域與滾動(dòng)條每次移動(dòng)的距離都是成正比的,所以第一個(gè)問題很好解決:
滾動(dòng)條可移動(dòng)范圍 / 滾動(dòng)條高度 = 內(nèi)容高度 / 內(nèi)容可視高度
每次點(diǎn)擊按鈕的時(shí)候滾動(dòng)條應(yīng)該移動(dòng)多少距離?
這里我是給參數(shù)distance設(shè)置一個(gè)值來決定每次點(diǎn)按鈕的時(shí)候,內(nèi)容區(qū)域應(yīng)該滾動(dòng)多少的距離。改變這個(gè)值可以改變內(nèi)容區(qū)域滾動(dòng)的快慢,如果有更好的處理方法和建議記得告訴我喔~
目前,內(nèi)容區(qū)域每次滾動(dòng)的距離是知道了,剩下的是計(jì)算滾動(dòng)條相對(duì)于應(yīng)該移動(dòng)多少距離?
滾動(dòng)條可移動(dòng)范圍 /滾動(dòng)條每次移動(dòng)距離 = 內(nèi)容區(qū)域高度 / 內(nèi)容區(qū)域每次移動(dòng)多少距離
效果如下:

這里還有一個(gè)問題,就是同時(shí)還得區(qū)分是單次點(diǎn)擊還是長(zhǎng)按。
所以得判斷一下從按下按鈕到松開時(shí)候的時(shí)長(zhǎng),目前設(shè)置為<100ms為單次點(diǎn)擊,否則為長(zhǎng)按:

拖動(dòng)滾動(dòng)條的時(shí)候,每移動(dòng)1px滾動(dòng)條,內(nèi)容區(qū)域需要移動(dòng)多少?
先知道每1PX的距離占滾動(dòng)條可移動(dòng)范圍的百分之幾,再用內(nèi)容區(qū)域高度除以所得的這個(gè)百分比,就得出滾動(dòng)條每移動(dòng)1px內(nèi)容區(qū)域相對(duì)滾動(dòng)多少距離了。
內(nèi)容區(qū)域滾動(dòng)的距離 = 內(nèi)容區(qū)域高度 / (滾動(dòng)條滾動(dòng)區(qū)域 / 1)

demo完整代碼如下:
注意:因?yàn)橛玫氖莝eajs寫的,所以稍微留意下文件的加載情況啦
css:
.wapper{scrollbar-3dlight-color:#000; position:relative; height:302px;width:300px;overflow:hidden;margin:0 auto;line-height:40px;text-align:center;}
.area{background-color:#E2E2EF;width:100%; position:absolute;top:0px;left:0px;}
.bar{position:absolute;top:0px;right:0px; height:100%;width:1rem;background-color:#ccc;}
.scroll,.middle,.forward,.backward{display:block;cursor:pointer;position:absolute;right:0px;width:100%;}
.forward,.backward{height:16px;background-color:#6868B1;}
.middle{background-color:rgba(255, 255, 255, 0.22);top:16px;cursor:auto;}
.scroll{position:absolute;top:0px;background-color:#C2C2E9;}
.forward{top:0px;}
.backward{bottom:0px;}
html:
<div class="wapper">
<div class="area">
<p>1、this is content</p>
<p>2、this is content</p>
<p>3、this is content</p>
<p>4、this is content</p>
<p>5、this is content</p>
<p>6、this is content</p>
<p>7、this is content</p>
<p>8、this is content</p>
<p>9、this is content</p>
<p>10、this is content</p>
<p>11、this is content</p>
</div>
<div class="bar">
<span class="forward"></span>
<span class="middle"><em class="scroll"></em></span>
<span class="backward"></span>
</div>
</div>
<script type="text/javascript" src="../../lib/seajs/sea.js"></script>
<script type="text/javascript" src="../../lib/base/1.0.x/base.js"></script>
<script type="text/javascript">
seajs.use(['lib/jquery/1.11.x/index.js', '_example/simulationScroll/simulationScroll.js'], function($, scroll) {
scroll.init({
wapper: $('.wapper'),
distance: 10,
});
});
js:
define(function(require, exports, module) {
'use strict';
var $ = require('lib/jquery/1.11.x/index.js');
var parameter = null;
//檢測(cè)設(shè)備類型
var startWhen, endWhen, moveWhen;
var u = navigator.userAgent;
if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) {
// 鼠標(biāo)
startWhen = 'mousedown';
endWhen = 'mouseup';
moveWhen = 'mousemove';
} else {
// 觸摸屏
startWhen = 'touchstart';
endWhen = 'touchend';
moveWhen = 'touchmove';
}
var simulation = {
_mousedownTimer: 0,
_setintervalId: 0,
_longClick: false, //是否長(zhǎng)點(diǎn)擊
_turnOf: null, //滾動(dòng)方向
init: function(options) {
var t = this;
t._scroll = $('.scroll'); //滾動(dòng)條
t._wapper = options.wapper.find('.area'); //內(nèi)容區(qū)域
t._distance = options.distance; //點(diǎn)擊上下按鈕頁面每次滾動(dòng)的距離
var forward = $('.forward'),
middle = $('.middle'),
backward = $('.backward');
parameter = {
view: t._wapper.parent().innerHeight(), //視圖高度
page: t._wapper.height(), //內(nèi)容高度
barArea: 0, //滾動(dòng)條可移動(dòng)范圍
scrollHeight: 0, //滾動(dòng)條的高度
scrollDistance: 0 //滾動(dòng)條每次滾動(dòng)的距離
};
//初始化滾動(dòng)條
if (parameter.page > parameter.view) {
//滾動(dòng)條可移動(dòng)范圍
middle.height( parameter.view - forward.height() * 2);
parameter.barArea = middle.height();
//滾動(dòng)條高度 = 滾動(dòng)條可滾動(dòng)范圍 / (頁面高度 / 可視高度)的百分比
parameter.scrollHeight = parameter.barArea / (parameter.page / parameter.view) ;
t._scroll.height(parameter.scrollHeight);
//滾動(dòng)條每次滾動(dòng)的距離 = 滾動(dòng)條可移動(dòng)范圍 * 頁面每次滾動(dòng)的百分比
parameter.scrollDistance = parameter.barArea / (parameter.page / t._distance) ;
//拖動(dòng)滾動(dòng)條
t.liveEvent();
//點(diǎn)擊向前按鈕,如果按下鼠標(biāo)到松開鼠標(biāo)的時(shí)長(zhǎng)<100ms,則為單次點(diǎn)擊
forward.bind(startWhen, function(e){
t._turnOf = 'forward';
t.longPress(e, t.direction );
}).bind(endWhen, function(e) {
t.mouseupFun(e, t.direction);
t._turnOf = null;
});
//點(diǎn)擊向后按鈕
backward.bind(startWhen, function(e){
t.longPress(e, t.direction );
}).bind(endWhen, function(e){
t.mouseupFun(e, t.direction );
});
//注冊(cè)鼠標(biāo)滾動(dòng)事件
// FF
if(document.addEventListener){
document.addEventListener('DOMMouseScroll',t.mouseRuning,false);
}
//其它瀏覽器
document.onmousewheel = t.mouseRuning;
}
},
//鼠標(biāo)滾動(dòng)
mouseRuning: function(e) {
var t = simulation;
e = e || window.event;
//ie、FF
if (e.detail) {
if (e.detail < 0) {
t._turnOf = 'forward';
t.direction ();
} else{
t._turnOf = null;
t.direction ();
}
// chrome
} else if(e.wheelDelta) {
if (e.wheelDelta > 0) {
t._turnOf = 'forward';
t.direction ();
} else{
t._turnOf = null;
t.direction ();
}
}
},
//判斷是否長(zhǎng)點(diǎn)擊
longPress: function(e, moveFun ) {
var t = this;
if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) {
e = e || window.event;
// 限制為鼠標(biāo)左鍵點(diǎn)擊才觸發(fā)
if (/^mouse/.test(e.type) && e.which !== 1) {
return;
}
}
t._setintervalId = setInterval(function(){
t._mousedownTimer += 10;
if( t._mousedownTimer >= 100 ){
moveFun();
}
},20);
},
mouseupFun: function(e, moveFun) {
var t = this;
if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) {
e = e || window.event;
// 限制為鼠標(biāo)左鍵點(diǎn)擊才觸發(fā)
if (/^mouse/.test(e.type) && e.which !== 1) {
return;
}
}
clearTimeout(t._setintervalId);
if( t._mousedownTimer < 100 ) {
moveFun();
}
t._mousedownTimer = 0;
},
direction:function() {
var t = simulation,
barTop = t._scroll.position().top,
pageTop = t._wapper.position().top,
moveDistance = {};
if ( t._turnOf === 'forward') {
//頁面到頂,不執(zhí)行任何操作
if (barTop == 0) {
return;
}
moveDistance = {
page: pageTop + t._distance,
bar: barTop - parameter.scrollDistance
}
//如果滾動(dòng)條距離頂部的距離少 < 每次滾動(dòng)的距離,或者已經(jīng)滾動(dòng)到頂部,則不再滾動(dòng)
if(barTop < parameter.scrollDistance || barTop <= 0){
moveDistance = {
page: 0,
bar: 0
}
}
} else {
//頁面到底,不執(zhí)行任何操作
if (barTop == parameter.barArea - parameter.scrollHeight){
return;
}
moveDistance = {
page: pageTop - t._distance,
bar: barTop + parameter.scrollDistance
};
// 如果滾動(dòng)條距離底部的距離值 < 每次滾動(dòng)的距離 或者已經(jīng)到底部,則一次滾到底
if ( moveDistance.bar + parameter.scrollHeight >= parameter.barArea) {
moveDistance = {
page: parameter.view - parameter.page,
bar: parameter.barArea - parameter.scrollHeight
};
}
}
t._scroll.css({top: moveDistance.bar});
t._wapper.css({top: moveDistance.page});
},
//拖動(dòng)滾動(dòng)條
liveEvent: function() {
var t = this,
draging = false,
currentY = 0,
lastY = 0,
pageY = 0;
//檢測(cè)設(shè)備類型
var _ua = function(e) {
var Pos = null;
if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) {
e = e || window.event;
// 限制為鼠標(biāo)左鍵點(diǎn)擊才觸發(fā)
if (/^mouse/.test(e.type) && e.which !== 1) {
return;
}
Pos = {
left : e.pageX,
top: e.pageY
}
} else {
Pos = {
left : e.originalEvent.targetTouches[0].pageX,
top: e.originalEvent.targetTouches[0].pageY
}
}
return Pos;
};
var _start = function(e) {
//監(jiān)控鼠標(biāo)
e.preventDefault();
if (t._scroll.get(0).setCapture) {
t._scroll.get(0).setCapture();
}
draging = true;
//記錄當(dāng)前滾動(dòng)條的坐標(biāo)
lastY = t._scroll.position().top;
//記錄按下鼠標(biāo)的坐標(biāo)
pageY = _ua(e).top;
};
var _drag = function(e) {
if( draging ) {
var pageTop = t._wapper.position().top;
var barTop = t._scroll.position().top;
//滾動(dòng)條每移動(dòng)1px,頁面相對(duì)滾動(dòng)Npx 再 * 當(dāng)前滾動(dòng)條的到頂部的距離
var pageMoveDistance = -(parameter.page / (parameter.barArea / 1)) * barTop;
if (lastY + ( _ua(e).top - pageY ) < 0) {
currentY = 0;
pageMoveDistance = 0;
} else if( lastY + ( _ua(e).top - pageY) + parameter.scrollHeight >= parameter.barArea) {
currentY = parameter.barArea - parameter.scrollHeight;
pageMoveDistance = parameter.view - parameter.page;
}
else {
currentY = lastY + ( _ua(e).top - pageY);
}
t._scroll.css({ top:currentY});
t._wapper.css({top: pageMoveDistance});
}
};
var _end = function(e) {
if (draging) {
draging = false;
//在IE下釋放對(duì)鼠標(biāo)的控制
if (t._scroll.get(0).setCapture) {
t._scroll.get(0).releaseCapture();
}
document.onmousemove = null;
document.onmouseup = null;
}
};
t._scroll.bind( startWhen, _start );
t._wapper.bind( startWhen, _start );
$(document).bind( moveWhen, _drag );
$(document).bind( endWhen, _end );
$(document).bind('blur', _end);
}
}
return simulation;
});
以上就是javascript模擬滾動(dòng)條實(shí)現(xiàn)代碼,希望對(duì)大家的學(xué)習(xí)有所幫助。
- JS自定義滾動(dòng)條效果
- js滾輪事件 js自定義滾動(dòng)條的實(shí)現(xiàn)
- 原生JS實(shí)現(xiàn)自定義滾動(dòng)條效果
- JS自定義滾動(dòng)條效果簡(jiǎn)單實(shí)現(xiàn)代碼
- JavaScript限定范圍拖拽及自定義滾動(dòng)條應(yīng)用(3)
- 原生js封裝自定義滾動(dòng)條
- 基于JavaScript實(shí)現(xiàn)自定義滾動(dòng)條
- JavaScript自定義瀏覽器滾動(dòng)條兼容IE、 火狐和chrome
- JavaScript 輪播圖和自定義滾動(dòng)條配合鼠標(biāo)滾輪分享代碼貼
- JS實(shí)現(xiàn)的頁面自定義滾動(dòng)條效果
- js實(shí)現(xiàn)自定義滾動(dòng)條的示例
相關(guān)文章
千萬不要錯(cuò)過的JavaScript高效對(duì)比數(shù)組差異方法
前端開發(fā)中,我們通常需要對(duì)比兩個(gè)數(shù)組對(duì)象的差異。這其中有很多種方法,但是有些方法會(huì)帶來一些問題,所以本文為大家準(zhǔn)備了一個(gè)高效方法,需要的可以參考一下2023-05-05
js實(shí)現(xiàn)隨機(jī)點(diǎn)名系統(tǒng)(實(shí)例講解)
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)隨機(jī)點(diǎn)名系統(tǒng)(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
JS中2種定時(shí)器的使用及清除的實(shí)現(xiàn)
本文主要介紹了JS中2種定時(shí)器的使用及清除的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Bootstrap的aria-label和aria-labelledby屬性實(shí)例詳解
這篇文章主要介紹了Bootstrap的aria-label和aria-labelledby屬性實(shí)例詳解,需要的朋友可以參考下2018-11-11

