zoukankan      html  css  js  c++  java
  • 模拟滚动条

    在工作中经常会遇到内容会超出固定的一个范围,超出的内容一般会使用到滚动条来滚动显示。

    但是用浏览器默认的滚动条经常被产品经理鄙视,可是用css却改变不了滚动条的样式,还好,有万能的js ^_^~~

    网上有各种各样的插件,但最顺手的还是自己写的,还可以一边撸一边当学习,自己动手丰衣足食  (*^__^*)

    其中这三个问题深深地困扰我:

    1、滚动条高度

    2、每次点击向上、向下按钮的时候滚动条应该移动多少距离

    3、每拖动1px滚动条,页面需要移动多少?

    整个的框架大概是长这样的:

     

    先来看看第一个问题。

      由于目前已经知道内容区域的高度和内容可视高度以及滚动条可滚动区域的高度了,由于内容区域与滚动条每次移动的距离都是成正比的,所以第一个问题很好解决:

      滚动条可移动范围 / 滚动条高度 = 内容高度 / 内容可视高度

    每次点击按钮的时候滚动条应该移动多少距离?

      这里我是给参数distance设置一个值来决定每次点按钮的时候,内容区域应该滚动多少的距离。改变这个值可以改变内容区域滚动的快慢,如果有更好的处理方法和建议记得告诉我喔~

    目前,内容区域每次滚动的距离是知道了,剩下的是计算滚动条相对于应该移动多少距离?

      滚动条可移动范围 /滚动条每次移动距离 = 内容区域高度 / 内容区域每次移动多少距离

    效果如下:

     

    这里还有一个问题,就是同时还得区分是单次点击还是长按。

    所以得判断一下从按下按钮到松开时候的时长,目前设置为<100ms为单次点击,否则为长按:

    拖动滚动条的时候,每移动1px滚动条,内容区域需要移动多少?

      先知道每1PX的距离占滚动条可移动范围的百分之几,再用内容区域高度除以所得的这个百分比,就得出滚动条每移动1px内容区域相对滚动多少距离了。

      内容区域滚动的距离 = 内容区域高度 / (滚动条滚动区域 / 1)

    demo完整代码如下:

    注意:

      因为用的是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;}
    View Code

    html:

     1 <div class="wapper">
     2     <div class="area">
     3         <p>1、this is content</p>
     4         <p>2、this is content</p>
     5         <p>3、this is content</p>
     6         <p>4、this is content</p>
     7         <p>5、this is content</p>
     8         <p>6、this is content</p>
     9         <p>7、this is content</p>
    10         <p>8、this is content</p>
    11         <p>9、this is content</p>
    12         <p>10、this is content</p>
    13         <p>11、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 });
    View Code

    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(/(WindowssNT|Macintosh)/) ) {
     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(/(WindowssNT|Macintosh)/) ) {
    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(/(WindowssNT|Macintosh)/) ) {
    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(/(WindowssNT|Macintosh)/) ) {
    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 });
    View Code
    【全都是流水账,仅仅记录进步的点滴】
  • 相关阅读:
    python 修改excel
    python 正则表达式规则收集
    anusplina 4.36版本使用提示 说明
    python 汉字编码问题
    python IOError: [Errno 22] invalid mode ('r') or filename:
    将矩阵数据转换为栅格图 filled.contour()
    将数值矩阵映射为栅格图
    一脚踩进java之基础篇23——常用API(Object、String)
    一脚踩进java之基础篇22——面向对象 (不同修饰符使用细节)
    一脚踩进java之基础篇21——面向对象 (访问修饰符、代码块)
  • 原文地址:https://www.cnblogs.com/Travel/p/5151932.html
Copyright © 2011-2022 走看看