在工做中常常會遇到內容會超出固定的一個範圍,超出的內容通常會使用到滾動條來滾動顯示。javascript
可是用瀏覽器默認的滾動條常常被產品經理鄙視,但是用css卻改變不了滾動條的樣式,還好,有萬能的js ^_^~~css
網上有各類各樣的插件,但最順手的仍是本身寫的,還能夠一邊擼一邊當學習,本身動手豐衣足食 (*^__^*)html
一、滾動條高度java
二、每次點擊向上、向下按鈕的時候滾動條應該移動多少距離jquery
三、每拖動1px滾動條,頁面須要移動多少?瀏覽器
整個的框架大概是長這樣的:app
先來看看第一個問題。框架
因爲目前已經知道內容區域的高度和內容可視高度以及滾動條可滾動區域的高度了,因爲內容區域與滾動條每次移動的距離都是成正比的,因此第一個問題很好解決:ide
滾動條可移動範圍 / 滾動條高度 = 內容高度 / 內容可視高度學習
這裏我是給參數distance設置一個值來決定每次點按鈕的時候,內容區域應該滾動多少的距離。改變這個值能夠改變內容區域滾動的快慢,若是有更好的處理方法和建議記得告訴我喔~
目前,內容區域每次滾動的距離是知道了,剩下的是計算滾動條相對於應該移動多少距離?
滾動條可移動範圍 /滾動條每次移動距離 = 內容區域高度 / 內容區域每次移動多少距離
效果以下:
這裏還有一個問題,就是同時還得區分是單次點擊仍是長按。
因此得判斷一下從按下按鈕到鬆開時候的時長,目前設置爲<100ms爲單次點擊,不然爲長按:
先知道每1PX的距離佔滾動條可移動範圍的百分之幾,再用內容區域高度除以所得的這個百分比,就得出滾動條每移動1px內容區域相對滾動多少距離了。
內容區域滾動的距離 = 內容區域高度 / (滾動條滾動區域 / 1)
注意:
由於用的是seajs寫的,因此稍微留意下文件的加載狀況啦
css:
1 .wapper{scrollbar-3dlight-color:#000; position:relative; height:302px;width:300px;overflow:hidden;margin:0 auto;line-height:40px;text-align:center;} 2 .area{background-color:#E2E2EF;width:100%; position:absolute;top:0px;left:0px;} 3 .bar{position:absolute;top:0px;right:0px; height:100%;width:1rem;background-color:#ccc;} 4 .scroll,.middle,.forward,.backward{display:block;cursor:pointer;position:absolute;right:0px;width:100%;} 5 .forward,.backward{height:16px;background-color:#6868B1;} 6 .middle{background-color:rgba(255, 255, 255, 0.22);top:16px;cursor:auto;} 7 .scroll{position:absolute;top:0px;background-color:#C2C2E9;} 8 .forward{top:0px;} 9 .backward{bottom:0px;}
html:
1 <div class="wapper"> 2 <div class="area"> 3 <p>一、this is content</p> 4 <p>二、this is content</p> 5 <p>三、this is content</p> 6 <p>四、this is content</p> 7 <p>五、this is content</p> 8 <p>六、this is content</p> 9 <p>七、this is content</p> 10 <p>八、this is content</p> 11 <p>九、this is content</p> 12 <p>十、this is content</p> 13 <p>十一、this is content</p> 14 </div> 15 <div class="bar"> 16 <span class="forward"></span> 17 <span class="middle"><em class="scroll"></em></span> 18 <span class="backward"></span> 19 </div> 20 </div> 21 22 <script type="text/javascript" src="../../lib/seajs/sea.js"></script> 23 <script type="text/javascript" src="../../lib/base/1.0.x/base.js"></script> 24 <script type="text/javascript"> 25 seajs.use(['lib/jquery/1.11.x/index.js', '_example/simulationScroll/simulationScroll.js'], function($, scroll) { 26 scroll.init({ 27 wapper: $('.wapper'), 28 distance: 10, 29 }); 30 });
js:
1 //兼容PC移動移動端 2 define(function(require, exports, module) { 3 4 'use strict'; 5 6 var $ = require('lib/jquery/1.11.x/index.js'); 7 8 var parameter = null; 9 10 //檢測設備類型 11 var startWhen, endWhen, moveWhen; 12 var u = navigator.userAgent; 13 14 if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { 15 // 鼠標 16 startWhen = 'mousedown'; 17 endWhen = 'mouseup'; 18 moveWhen = 'mousemove'; 19 } else { 20 // 觸摸屏 21 startWhen = 'touchstart'; 22 endWhen = 'touchend'; 23 moveWhen = 'touchmove'; 24 } 25 26 var simulation = { 27 28 _mousedownTimer: 0, 29 _setintervalId: 0, 30 _longClick: false, //是否長點擊 31 _turnOf: null, //滾動方向 32 33 init: function(options) { 34 35 var t = this; 36 37 t._scroll = $('.scroll'); //滾動條 38 39 t._wapper = options.wapper.find('.area'); //內容區域 40 t._distance = options.distance; //點擊上下按鈕頁面每次滾動的距離 41 42 var forward = $('.forward'), 43 middle = $('.middle'), 44 backward = $('.backward'); 45 46 parameter = { 47 view: t._wapper.parent().innerHeight(), //視圖高度 48 page: t._wapper.height(), //內容高度 49 barArea: 0, //滾動條可移動範圍 50 scrollHeight: 0, //滾動條的高度 51 scrollDistance: 0 //滾動條每次滾動的距離 52 }; 53 54 //初始化滾動條 55 if (parameter.page > parameter.view) { 56 57 //滾動條可移動範圍 58 middle.height( parameter.view - forward.height() * 2); 59 60 parameter.barArea = middle.height(); 61 62 //滾動條高度 = 滾動條可滾動範圍 / (頁面高度 / 可視高度)的百分比 63 parameter.scrollHeight = parameter.barArea / (parameter.page / parameter.view) ; 64 t._scroll.height(parameter.scrollHeight); 65 66 //滾動條每次滾動的距離 = 滾動條可移動範圍 * 頁面每次滾動的百分比 67 parameter.scrollDistance = parameter.barArea / (parameter.page / t._distance) ; 68 69 //拖動滾動條 70 t.liveEvent(); 71 72 //點擊向前按鈕,若是按下鼠標到鬆開鼠標的時長<100ms,則爲單次點擊 73 forward.bind(startWhen, function(e){ 74 75 t._turnOf = 'forward'; 76 77 t.longPress(e, t.direction ); 78 79 }).bind(endWhen, function(e) { 80 81 t.mouseupFun(e, t.direction); 82 83 t._turnOf = null; 84 85 }); 86 87 //點擊向後按鈕 88 backward.bind(startWhen, function(e){ 89 90 t._turnOf = null; 91 92 t.longPress(e, t.direction ); 93 94 }).bind(endWhen, function(e){ 95 96 t.mouseupFun(e, t.direction ); 97 98 }); 99 100 //註冊鼠標滾動事件 101 // FF 102 if(document.addEventListener){ 103 document.addEventListener('DOMMouseScroll',t.mouseRuning,false); 104 } 105 106 //其它瀏覽器 107 document.onmousewheel = t.mouseRuning; 108 } 109 }, 110 111 //鼠標滾動 112 mouseRuning: function(e) { 113 114 e = e || window.event; 115 var t = simulation; 116 var detail = e.detail || e.wheelDelta; 117 118 switch(true){ 119 case detail>=100: 120 case detail<=0 && detail>=-100: 121 t._turnOf = 'forward'; 122 123 break; 124 125 case detail<=-100: 126 case detail>0 && detail<=100: 127 t._turnOf = null; 128 break; 129 } 130 131 t.direction (); 132 }, 133 134 //判斷是否長點擊 135 longPress: function(e, moveFun ) { 136 137 var t = this; 138 139 if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { 140 e = e || window.event; 141 142 // 限制爲鼠標左鍵點擊才觸發 143 if (/^mouse/.test(e.type) && e.which !== 1) { 144 return; 145 } 146 } 147 148 t._setintervalId = setInterval(function(){ 149 150 t._mousedownTimer += 10; 151 152 if( t._mousedownTimer >= 100 ){ 153 154 moveFun(); 155 } 156 157 },20); 158 }, 159 160 mouseupFun: function(e, moveFun) { 161 162 var t = this; 163 164 if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { 165 e = e || window.event; 166 167 // 限制爲鼠標左鍵點擊才觸發 168 if (/^mouse/.test(e.type) && e.which !== 1) { 169 return; 170 } 171 } 172 173 clearTimeout(t._setintervalId); 174 175 if( t._mousedownTimer < 100 ) { 176 177 moveFun(); 178 } 179 180 t._mousedownTimer = 0; 181 }, 182 183 direction:function() { 184 var t = simulation, 185 barTop = t._scroll.position().top, 186 pageTop = t._wapper.position().top, 187 moveDistance = {}; 188 189 if ( t._turnOf === 'forward') { 190 191 //頁面到頂,不執行任何操做 192 if (barTop < 0) { 193 194 return; 195 } 196 197 moveDistance = { 198 page: pageTop + t._distance, 199 bar: barTop - parameter.scrollDistance 200 } 201 202 //若是滾動條距離頂部的距離少 < 每次滾動的距離,或者已經滾動到頂部,則再也不滾動 203 if(barTop < parameter.scrollDistance || barTop <= 0){ 204 205 moveDistance = { 206 page: 0, 207 bar: 0 208 } 209 } 210 } else { 211 212 //頁面到底,不執行任何操做 213 if (barTop == parameter.barArea - parameter.scrollHeight){ 214 return; 215 } 216 217 moveDistance = { 218 page: pageTop - t._distance, 219 bar: barTop + parameter.scrollDistance 220 }; 221 222 // 若是滾動條距離底部的距離值 < 每次滾動的距離 或者已經到底部,則一次滾到底 223 if ( moveDistance.bar + parameter.scrollHeight >= parameter.barArea) { 224 225 moveDistance = { 226 page: parameter.view - parameter.page, 227 bar: parameter.barArea - parameter.scrollHeight 228 }; 229 230 } 231 } 232 233 t._scroll.css({top: moveDistance.bar}); 234 t._wapper.css({top: moveDistance.page}); 235 }, 236 237 //拖動滾動條 238 liveEvent: function() { 239 var t = this, 240 draging = false, 241 currentY = 0, 242 lastY = 0, 243 pageY = 0; 244 245 //檢測設備類型 246 var _ua = function(e) { 247 248 var Pos = null; 249 250 if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) { 251 e = e || window.event; 252 253 // 限制爲鼠標左鍵點擊才觸發 254 if (/^mouse/.test(e.type) && e.which !== 1) { 255 return; 256 } 257 258 Pos = { 259 left : e.pageX, 260 top: e.pageY 261 } 262 263 } else { 264 Pos = { 265 left : e.originalEvent.targetTouches[0].pageX, 266 top: e.originalEvent.targetTouches[0].pageY 267 } 268 } 269 return Pos; 270 }; 271 272 var _start = function(e) { 273 274 //監控鼠標 275 e.preventDefault(); 276 277 if (t._scroll.get(0).setCapture) { 278 t._scroll.get(0).setCapture(); 279 } 280 281 draging = true; 282 283 //記錄當前滾動條的座標 284 lastY = t._scroll.position().top; 285 286 //記錄按下鼠標的座標 287 pageY = _ua(e).top; 288 }; 289 290 var _drag = function(e) { 291 292 if( draging ) { 293 294 var pageTop = t._wapper.position().top; 295 var barTop = t._scroll.position().top; 296 297 //滾動條每移動1px,頁面相對滾動Npx 再 * 當前滾動條的到頂部的距離 298 var pageMoveDistance = -(parameter.page / (parameter.barArea / 1)) * barTop; 299 300 if (lastY + ( _ua(e).top - pageY ) < 0) { 301 currentY = 0; 302 pageMoveDistance = 0; 303 304 } else if( lastY + ( _ua(e).top - pageY) + parameter.scrollHeight >= parameter.barArea) { 305 currentY = parameter.barArea - parameter.scrollHeight; 306 pageMoveDistance = parameter.view - parameter.page; 307 } 308 else { 309 currentY = lastY + ( _ua(e).top - pageY); 310 } 311 312 t._scroll.css({ top:currentY}); 313 t._wapper.css({top: pageMoveDistance}); 314 } 315 }; 316 317 var _end = function(e) { 318 319 if (draging) { 320 321 draging = false; 322 323 //在IE下釋放對鼠標的控制 324 if (t._scroll.get(0).setCapture) { 325 t._scroll.get(0).releaseCapture(); 326 } 327 328 document.onmousemove = null; 329 document.onmouseup = null; 330 } 331 }; 332 333 t._scroll.bind( startWhen, _start ); 334 335 t._wapper.bind( startWhen, _start ); 336 337 $(document).bind( moveWhen, _drag ); 338 339 $(document).bind( endWhen, _end ); 340 341 $(document).bind('blur', _end); 342 } 343 } 344 return simulation; 345 });