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

JavaScript 사용자 정의 스크롤 막대 구현 code_javascript 기술

WBOY
WBOY원래의
2016-05-16 15:16:161196검색

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

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

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

이 세 가지 질문이 저를 매우 괴롭힙니다.

  • 1. 스크롤바 높이
  • 2. 위쪽 및 아래쪽 버튼을 클릭할 때마다 스크롤바가 어느 정도 이동해야 합니까?
  • 3. 스크롤바를 1px 드래그할 때마다 페이지는 얼마나 이동해야 하나요?

전체 프레임은 아마도 다음과 같습니다:

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

콘텐츠 영역의 높이, 콘텐츠의 시각적 높이, 스크롤 막대의 스크롤 가능 영역 높이를 이미 알고 있으므로 콘텐츠 영역과 스크롤 막대의 각 이동 거리는 비례하므로 , 첫 번째 질문이 매우 좋습니다. 해결책:

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

버튼을 클릭할 때마다 스크롤 막대가 얼마나 멀리 이동해야 합니까?

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

현재 콘텐츠 영역의 각 스크롤 거리가 알려져 있습니다. 남은 것은 스크롤 막대가 얼마나 멀리 이동해야 하는지 계산하는 것입니다.

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

효과는 다음과 같습니다.

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

따라서 버튼을 눌렀을 때부터 놓을 때까지의 시간을 판단해야 합니다. 현재는 한 번의 클릭에 대해 <100ms로 설정되어 있으며, 그렇지 않으면 길게 누르는 것입니다.

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

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

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

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

참고: 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 시뮬레이션 스크롤바 구현 코드입니다.

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