在工作中經常會遇到內容會超出固定的一個范圍,超出的內容一般會使用到滾動條來滾動顯示。
但是用浏覽器默認的滾動條經常被產品經理鄙視,可是用css卻改變不了滾動條的樣式,還好,有萬能的js ^_^~~
網上有各種各樣的插件,但最順手的還是自己寫的,還可以一邊撸一邊當學習,自己動手豐衣足食 (*^__^*)
其中這三個問題深深地困擾我:
整個的框架大概是長這樣的:
先來看看第一個問題。
由於目前已經知道內容區域的高度和內容可視高度以及滾動條可滾動區域的高度了,由於內容區域與滾動條每次移動的距離都是成正比的,所以第一個問題很好解決:
滾動條可移動范圍 / 滾動條高度 = 內容高度 / 內容可視高度
每次點擊按鈕的時候滾動條應該移動多少距離?
這裡我是給參數distance設置一個值來決定每次點按鈕的時候,內容區域應該滾動多少的距離。改變這個值可以改變內容區域滾動的快慢,如果有更好的處理方法和建議記得告訴我喔~
目前,內容區域每次滾動的距離是知道了,剩下的是計算滾動條相對於應該移動多少距離?
滾動條可移動范圍 /滾動條每次移動距離 = 內容區域高度 / 內容區域每次移動多少距離
效果如下:
這裡還有一個問題,就是同時還得區分是單次點擊還是長按。
所以得判斷一下從按下按鈕到松開時候的時長,目前設置為<100ms為單次點擊,否則為長按:
拖動滾動條的時候,每移動1px滾動條,內容區域需要移動多少?
先知道每1PX的距離占滾動條可移動范圍的百分之幾,再用內容區域高度除以所得的這個百分比,就得出滾動條每移動1px內容區域相對滾動多少距離了。
內容區域滾動的距離 = 內容區域高度 / (滾動條滾動區域 / 1)
demo完整代碼如下:
注意:因為用的是seajs寫的,所以稍微留意下文件的加載情況啦
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; //檢測設備類型 var startWhen, endWhen, moveWhen; var u = navigator.userAgent; if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { // 鼠標 startWhen = 'mousedown'; endWhen = 'mouseup'; moveWhen = 'mousemove'; } else { // 觸摸屏 startWhen = 'touchstart'; endWhen = 'touchend'; moveWhen = 'touchmove'; } var simulation = { _mousedownTimer: 0, _setintervalId: 0, _longClick: false, //是否長點擊 _turnOf: null, //滾動方向 init: function(options) { var t = this; t._scroll = $('.scroll'); //滾動條 t._wapper = options.wapper.find('.area'); //內容區域 t._distance = options.distance; //點擊上下按鈕頁面每次滾動的距離 var forward = $('.forward'), middle = $('.middle'), backward = $('.backward'); parameter = { view: t._wapper.parent().innerHeight(), //視圖高度 page: t._wapper.height(), //內容高度 barArea: 0, //滾動條可移動范圍 scrollHeight: 0, //滾動條的高度 scrollDistance: 0 //滾動條每次滾動的距離 }; //初始化滾動條 if (parameter.page > parameter.view) { //滾動條可移動范圍 middle.height( parameter.view - forward.height() * 2); parameter.barArea = middle.height(); //滾動條高度 = 滾動條可滾動范圍 / (頁面高度 / 可視高度)的百分比 parameter.scrollHeight = parameter.barArea / (parameter.page / parameter.view) ; t._scroll.height(parameter.scrollHeight); //滾動條每次滾動的距離 = 滾動條可移動范圍 * 頁面每次滾動的百分比 parameter.scrollDistance = parameter.barArea / (parameter.page / t._distance) ; //拖動滾動條 t.liveEvent(); //點擊向前按鈕,如果按下鼠標到松開鼠標的時長<100ms,則為單次點擊 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; }); //點擊向後按鈕 backward.bind(startWhen, function(e){ t.longPress(e, t.direction ); }).bind(endWhen, function(e){ t.mouseupFun(e, t.direction ); }); //注冊鼠標滾動事件 // FF if(document.addEventListener){ document.addEventListener('DOMMouseScroll',t.mouseRuning,false); } //其它浏覽器 document.onmousewheel = t.mouseRuning; } }, //鼠標滾動 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 (); } } }, //判斷是否長點擊 longPress: function(e, moveFun ) { var t = this; if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { e = e || window.event; // 限制為鼠標左鍵點擊才觸發 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; // 限制為鼠標左鍵點擊才觸發 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') { //頁面到頂,不執行任何操作 if (barTop == 0) { return; } moveDistance = { page: pageTop + t._distance, bar: barTop - parameter.scrollDistance } //如果滾動條距離頂部的距離少 < 每次滾動的距離,或者已經滾動到頂部,則不再滾動 if(barTop < parameter.scrollDistance || barTop <= 0){ moveDistance = { page: 0, bar: 0 } } } else { //頁面到底,不執行任何操作 if (barTop == parameter.barArea - parameter.scrollHeight){ return; } moveDistance = { page: pageTop - t._distance, bar: barTop + parameter.scrollDistance }; // 如果滾動條距離底部的距離值 < 每次滾動的距離 或者已經到底部,則一次滾到底 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}); }, //拖動滾動條 liveEvent: function() { var t = this, draging = false, currentY = 0, lastY = 0, pageY = 0; //檢測設備類型 var _ua = function(e) { var Pos = null; if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { e = e || window.event; // 限制為鼠標左鍵點擊才觸發 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) { //監控鼠標 e.preventDefault(); if (t._scroll.get(0).setCapture) { t._scroll.get(0).setCapture(); } draging = true; //記錄當前滾動條的坐標 lastY = t._scroll.position().top; //記錄按下鼠標的坐標 pageY = _ua(e).top; }; var _drag = function(e) { if( draging ) { var pageTop = t._wapper.position().top; var barTop = t._scroll.position().top; //滾動條每移動1px,頁面相對滾動Npx 再 * 當前滾動條的到頂部的距離 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下釋放對鼠標的控制 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模擬滾動條實現代碼,希望對大家的學習有所幫助。