>  기사  >  웹 프론트엔드  >  JavaScript 사용자 정의 스크롤 막대 구현 코드

JavaScript 사용자 정의 스크롤 막대 구현 코드

高洛峰
高洛峰원래의
2017-01-07 13:31:241199검색

작업을 하다 보면 일정 범위를 초과하는 콘텐츠를 자주 접하게 되는데, 일반적으로 초과된 콘텐츠를 스크롤하여 표시하는 데 스크롤바를 사용합니다.

그런데 브라우저의 기본 스크롤바를 사용하면 제품 관리자가 무시하는 경우가 많은데 CSS를 사용하면 스크롤바의 스타일을 변경할 수 없습니다 ^_^~~

온라인 다양한 플러그인이 있지만 가장 편리한 것은 직접 작성하는 것입니다. 놀면서 배울 수도 있고, 음식과 옷도 스스로 충분히 만들 수 있습니다(*^__^*)

이 세 가지 문제가 매우 고민됩니다. 나:

1. 스크롤바 높이

2. 위쪽 및 아래쪽 버튼을 클릭할 때마다 스크롤바가 얼마나 움직여야 하는지

3. 드래그 바당 1px 스크롤, 페이지를 얼마나 이동해야 하나요?

전체 프레임워크는 아마도 다음과 같습니다.

JavaScript 사용자 정의 스크롤 막대 구현 코드

먼저 첫 번째 질문을 살펴보겠습니다.

우리는 콘텐츠 영역의 높이, 콘텐츠의 시각적 높이, 스크롤 막대의 스크롤 가능 영역 높이를 이미 알고 있으므로 콘텐츠 영역은 각 이동 거리에 비례하므로 스크롤바가 있으므로 첫 번째 문제는 쉽게 해결됩니다:

스크롤바 이동 가능 범위 / 스크롤바 높이 = 콘텐츠 높이 / 콘텐츠 표시 높이

매번 스크롤바를 얼마나 움직여야 할까요? 버튼이 클릭되었나요?

여기서는 버튼을 클릭할 때마다 콘텐츠 영역이 스크롤되는 거리를 결정하기 위해 매개변수 거리 값을 설정합니다. 이 값을 변경하면 콘텐츠 영역의 스크롤 속도가 변경될 수 있습니다. 더 나은 처리 방법이나 제안 사항이 있으면 알려주세요~

현재 콘텐츠 영역의 각 스크롤 거리가 알려져 있으며 나머지는 스크롤을 계산하려면 막대가 서로를 기준으로 얼마나 멀리 이동해야 합니까?

스크롤바 이동 범위 / 스크롤바가 매번 이동하는 거리 = 콘텐츠 영역의 높이 / 매번 콘텐츠 영역이 이동하는 거리

효과는 다음과 같습니다.

JavaScript 사용자 정의 스크롤 막대 구현 코드

여기서 또 다른 문제가 있는데, 바로 한 번의 클릭과 길게 누르는 것을 구별해야 한다는 것입니다.

따라서 버튼을 누른 후 놓을 때까지의 시간을 판단해야 합니다. 현재는 한 번 클릭할 경우

JavaScript 사용자 정의 스크롤 막대 구현 코드

스크롤 막대를 드래그할 때 스크롤 막대 1px을 움직일 때마다 콘텐츠 영역을 얼마나 움직여야 합니까?

먼저 1PX 거리마다 스크롤 막대의 이동 가능 범위가 차지하는 비율을 파악한 다음 콘텐츠 영역 높이를 얻은 백분율로 나누어 스크롤 1px마다 콘텐츠 영역의 상대적인 스크롤 거리를 구합니다. 술집. .

콘텐츠 영역 스크롤 거리 = 콘텐츠 영역 높이/(스크롤바 스크롤 영역/1)

JavaScript 사용자 정의 스크롤 막대 구현 코드

데모의 전체 코드는 다음과 같습니다.

참고: 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([&#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,
 });
});

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;
});

위는 자바스크립트 시뮬레이션 스크롤바입니다. 코드를 구현해 보았는데, 모두의 학습에 도움이 되기를 바랍니다.

JavaScript 사용자 정의 스크롤바 구현 코드와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.