Home > Web Front-end > JS Tutorial > body text

JavaScript custom scroll bar implementation code

高洛峰
Release: 2017-01-07 13:31:24
Original
1266 people have browsed it

In work, we often encounter content that exceeds a fixed range. Generally, scroll bars are used to scroll and display the exceeded content.

But using the browser's default scroll bar is often looked down upon by product managers, but using css cannot change the style of the scroll bar. Fortunately, there is a universal js ^_^~~

online There are various plug-ins, but the most convenient one is to write it yourself. You can also play and learn at the same time, and make enough food and clothing by yourself (*^__^*)

These three problems are deeply troubled. Me:

1. Scroll bar height

2. How far the scroll bar should move each time the up and down buttons are clicked

3. 1px scrolling per drag Bar, how much does the page need to move?

The entire framework probably looks like this:

JavaScript custom scroll bar implementation code

Let’s take a look at the first question first.

Since we already know the height of the content area, the visual height of the content and the height of the scrollable area of ​​the scroll bar, since the content area is proportional to the distance of each movement of the scroll bar, the first The problem is easy to solve:

Scroll bar movable range / scroll bar height = content height / content visible height

How far should the scroll bar move every time the button is clicked?

Here I set a value for the parameter distance to determine how far the content area should scroll each time the button is clicked. Changing this value can change the scrolling speed of the content area. If you have better processing methods and suggestions, please tell me~

Currently, the distance of each scrolling of the content area is known, and the rest is to calculate the scrolling How far should the bars move relative to each other?

The movable range of the scroll bar / the distance the scroll bar moves each time = the height of the content area / the distance the content area moves each time

The effect is as follows:

JavaScript custom scroll bar implementation code

There is another problem here, that is, you have to distinguish between a single click and a long press.

So you have to judge the duration from pressing the button to releasing it. Currently it is set to

JavaScript custom scroll bar implementation code

When dragging the scroll bar, how much does the content area need to move for each 1px scroll bar movement?

First know what percentage of the scroll bar's movable range each 1PX distance accounts for, and then divide the content area height by the percentage obtained to get the relative scrolling distance of the content area for each 1px movement of the scroll bar. .

Content area scrolling distance = content area height / (scroll bar scrolling area / 1)

JavaScript custom scroll bar implementation code

The complete code of the demo is as follows:

Note: Because it is written in seajs, please pay a little attention to the loading of the file

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;}
Copy after login

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([&#39;lib/jquery/1.11.x/index.js&#39;, &#39;_example/simulationScroll/simulationScroll.js&#39;], function($, scroll) {
 scroll.init({
  wapper: $(&#39;.wapper&#39;),
  distance: 10,
 });
});
Copy after login

js:

define(function(require, exports, module) {
 
 &#39;use strict&#39;;
 
 var $ = require(&#39;lib/jquery/1.11.x/index.js&#39;);
 
 var parameter = null;
 
 //检测设备类型
 var startWhen, endWhen, moveWhen;
 var u = navigator.userAgent;
 
 if ( u.match(/\b(Windows\sNT|Macintosh)\b/) ) {
  // 鼠标
  startWhen = &#39;mousedown&#39;;
  endWhen = &#39;mouseup&#39;;
  moveWhen = &#39;mousemove&#39;;
 } else {
  // 触摸屏
  startWhen = &#39;touchstart&#39;;
  endWhen = &#39;touchend&#39;;
  moveWhen = &#39;touchmove&#39;;
 }
 
 var simulation = {
 
  _mousedownTimer: 0,
  _setintervalId: 0,
  _longClick: false, //是否长点击
  _turnOf: null, //滚动方向
 
  init: function(options) {
 
   var t = this;
 
   t._scroll = $(&#39;.scroll&#39;); //滚动条
 
   t._wapper = options.wapper.find(&#39;.area&#39;); //内容区域
   t._distance = options.distance; //点击上下按钮页面每次滚动的距离
 
   var forward = $(&#39;.forward&#39;),
    middle = $(&#39;.middle&#39;),
    backward = $(&#39;.backward&#39;);
 
   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 = &#39;forward&#39;;
 
     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(&#39;DOMMouseScroll&#39;,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 = &#39;forward&#39;;
 
     t.direction ();
 
    } else{
 
     t._turnOf = null;
     t.direction ();
    }
   // chrome
   } else if(e.wheelDelta) {
 
    if (e.wheelDelta > 0) {
 
     t._turnOf = &#39;forward&#39;;
 
     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 === &#39;forward&#39;) {
 
     //页面到顶,不执行任何操作
     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(&#39;blur&#39;, _end);
  }
 }
 return simulation;
});
Copy after login

The above is the javascript simulation scroll bar implementation code, I hope it will be helpful to everyone learning helps.

For more articles related to JavaScript custom scroll bar implementation code, please pay attention to the PHP Chinese website!


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template