javascript自定义滚动条实现代码_javascript技巧

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

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

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

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

  • 1、滚动条高度
  • 2、每次点击向上、向下按钮的时候滚动条应该移动多少距离
  • 3、每拖动1px滚动条,页面需要移动多少?

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

先来看看第一个问题。

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

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

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

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

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

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

效果如下:

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

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

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

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

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

demo完整代码如下:

注意:因为用的是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模拟滚动条实现代码,希望对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索javascript
滚动条
javascript滚动条事件、javascript 滚动条、javascript监听滚动条、javascript操作滚动条、javascript控制滚动条,以便于您获取更多的相关知识。

时间: 2016-02-02

javascript自定义滚动条实现代码_javascript技巧的相关文章

javascript模拟滚动条实现代码_javascript技巧

0% 0% 人族 SKY流--强大的中国选手人皇sky的成名绝技 KUA流--多不兵配合MK,前期可谓遇佛神通杀 3法流--好象只是很好打兽族,打精灵还得配合小炮 骑士狮鸠流--配合圣骑的3级光环全防心灵之火,绝对bug 飘逸流--3蛋的成名绝技,首发圣骑,打得亡灵一般没的脾气 机械流--飞机加坦克,曾经风靡一时,moon也吃亏无数 万精油--3发+火枪+小炮,不变应万变的打法 兽族 跑狼骑--狼骑的高速移动,城攻与网,拆家起来无人能敌 速飞龙--比较投机的打法,一旦投机成功,对方可以直接gg

Javascript 自定义类型方法小结_javascript技巧

1. 定义类型 复制代码 代码如下: function UserObject(parameter) { } parameter 可省略,相当于C#中构造函数参数. 2. 实例化自定义类型 复制代码 代码如下: <script type="text/javascript"> function userobject(parameter){ } //myobject is now an object of type userobject! var myobject=new use

js/ajax跨越访问-jsonp的原理和实例(javascript和jquery实现代码)_javascript技巧

很庆幸,我又见到了末日后新升的太阳,所以我还能在这里写文章,言归正传哈,最近做了一个项目,需要用子域名调用主域名下的一个现有的功能,于是想到了用jsonp来解决,在我们平常的项目中不乏有这种需求的朋友,于是记录下来以便以后查阅同时也希望能帮到大家. 什么是JSONP协议? JSONP即JSON with Padding.由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名.协议.端口)的资源.如果要进行跨域请求,我们可以通过使用html的script标记来进行跨域请求,并在响应

JavaScript Konami Code 实现代码_javascript技巧

在 Facebook 上有一个彩蛋: 登录 facebook.com ,点击你首页的任何地方,键盘输入 Up, Up, Down, Down, Left, Right, Left, Right, B, A, Enter 后,再点击页面或滚动一下滚动条,你会发现特殊的变化(如下图),嘿嘿 ^^ 玩过"魂斗罗"的朋友,肯定一眼就能看出输入的字符原来就是"魂斗罗"中的"秘技".其实"秘技"的术语叫 Konami Code,详细见图示

最短的javascript:地址栏载入脚本代码_javascript技巧

不过脚本比较长的时候,需要复制密密麻麻一大段到地址栏里,显得很不美观,而且脚本修改起来也很不容易.因此一般先把脚本写在单独一个文件里,然后用javascript: 的形式动态载入脚本到页面中.不少网页插件都是用这个方法载入. 平时,我们用最简单的代码实现动态载入: 复制代码 代码如下: javascript:var o=document.createElement('script');o.src='...';document.body.appendChild(o);void(0) 当然,这对于载

Javascript base64编码实现代码_javascript技巧

复制代码 代码如下: /* * base64编码 */ var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var base64DecodeChars = new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1

javascript生成随机颜色示例代码_javascript技巧

复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&qu

javascript 拖放效果实现代码_javascript技巧

有许多理由让你在页面中加入拖放的功能,其中最简单的理由是重新组织数据.举个例子,你可能希望用户能够重组一系列的页面元素,通过放置一个input或 select组件在各个元素的旁边来代表它们的顺序是一种解决方案,使该组元素可以被拖放是一种替代方案.或者也许你想在网站上拥有一个可以被用户移动的导航窗口.这些都是使用拖放功能的简单理由,因为你能够实现! 在你的网页上实现拖放的效果并不是很复杂.首先,我们知道鼠标的位置,然后我们需要了解用户什么时候点击一个元素,以至于我们知道要准备开始拖动它,最后我们要

JavaScript 拖拽实例代码_javascript技巧

一.JS 拖拽的实现实例代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>拖拽js</title> <style type="text/css"> html, body { overflow:hidden; } body, div, { margin:0; pad