ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript カスタム スクロール バーの実装コード

JavaScript カスタム スクロール バーの実装コード

高洛峰
高洛峰オリジナル
2017-01-07 13:31:241263ブラウズ

仕事上、一定の範囲を超えた内容に遭遇することがよくありますが、超えた内容をスクロールして表示するためにスクロールバーが使用されます。

しかし、ブラウザのデフォルトのスクロールバーを使用することはプロダクトマネージャーに軽蔑されがちですが、スクロールバーのスタイルはCSSを使用して変更することはできません、幸いなことにユニバーサルjsがあります^_^~~

さまざまなものがあります。プラグインはインターネット上にありますが、一番便利なのは自分で書くことです。遊びながら勉強することもできますし、食べ物や衣服も自分で作ることができます。

1. スクロールバーの高さ

2、上下ボタンをクリックするたびにスクロールバーはどのくらい移動する必要がありますか

3. 1pxのスクロールバーをドラッグするたびにページはどのくらい移動する必要がありますか?

全体のフレームワークはおそらく次のようになります:

JavaScript カスタム スクロール バーの実装コードまず最初の質問を見てみましょう。

コンテンツ領域の高さ、コンテンツの視覚的な高さ、スクロールバーのスクロール可能領域の高さはすでにわかっているため、コンテンツ領域とスクロールバーの間の距離はそれぞれの動きに比例するため、最初の問題は簡単に解決できます:

スクロールバーの可動範囲/スクロールバーの高さ=コンテンツの高さ/コンテンツの表示高さ

ボタンをクリックするたびにスクロールバーはどこまで移動する必要がありますか?

ここでは、ボタンがクリックされるたびにコンテンツ領域をどこまでスクロールするかを決定するパラメータ距離の値を設定します。この値を変更すると、コンテンツ領域のスクロール速度を変更できます。より良い処理方法と提案があれば、教えてください~

現在、残りはコンテンツ領域の各スクロールの距離を計算することです。スクロールバーはどこまで移動しますか?

スクロールバーの移動範囲 / 時間当たりのスクロールバーの移動距離 = コンテンツ領域の高さ / コンテンツ領域の時間当たりの移動距離

効果は次のとおりです:

JavaScript カスタム スクロール バーの実装コード ここで別の問題があります。つまり、区別する必要があります。 1回クリックまたは長押しと同時に。

そのため、ボタンを押してから離すまでの時間を判断する必要があります。現在、シングルクリックの場合は

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シミュレーションスクロールバーの実装コードです。するだろうすべての人に役立つようにする 学ぶことは役に立ちます。

JavaScript カスタム スクロール バー実装コードに関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。