原生JavaScript实现滚动条

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生JavaScript实现滚动条相关的知识,希望对你有一定的参考价值。

没事找事,明明overflow:scroll|auto就可以,只是难看点(实际上css也能设置)。只当练习写拖拽、监听事件、位置检测了。

原理是对滑动条块进行监听,按下鼠标按键后,监听鼠标移动,然后根据滑动条块移动的百分比算出滚动区域的滚动程度,用marginLeft进行滚动。具体的写在注释里。

整体弄成了一个对象,防止各种乱七八糟的数据污染全局变量。另外,对象内部调用的函数也都写到了对象构造函数的里面,由于对象作用域链的原理,外部无法进行调用,防止不小心在外部调用。

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title>Blank Page for Rich Text Editing</title>
  5     <meta http-equiv="content-type" name="author" content="Fujihara No Kokukiyo" />
  6     <meta charset="utf-8" />
  7 </head>
  8 <style rel="stylesheet" type="text/css">
  9     .outer{width:500px;border:1px solid black;overflow:hidden;margin:50px 0 0 100px;}
 10     .test_div{width:1200px;background-image:linear-gradient(90deg,lightcoral 0%,lightgreen 50%,lightblue 100%);height:150px;}
 11     .slider_bar,.slider_block{ border-radius:5px;}
 12     .slider_bar{position:relative;width:80%;margin:5px auto 5px auto;background-color:lightgreen;height:5px;}
 13     .slider_block{width:20px;height:5px;background-color:grey;cursor:pointer;position:absolute;}
 14 </style>
 15 <script type="text/javascript">
 16     window.onload=function(){
 17         /**
 18          * 滑动条对象构造函数,
 19          * 内含其他功能性函数,利用函数作用域链的原理,防止自己随意调用
 20          * 兼容:firefox、opera、chrome
 21          * ie没试,然而显然不兼容旧版本ie(8及之前),因为旧版本ie添加事件监听函数的方法不同。如若要兼容ie,还需要添加其他函数
 22          * js生成的滑动条类名为slider_bar、滑动块类型为slider_block,可用css样式自己设置大小、颜色等。
 23          * 滑动条左右padding未限制滑动条界限,如若需要限制,须在计算部分进行细小修改,加算padding,此处略去。
 24          *
 25          * @param {DOMElement} slider_content 被滚动的元素(不是被滚动元素的父元素)
 26          */
 27         function Slider(slider_content){
 28             //slider_instance为对象本身(在事件处理函数中会进行访问,而事件处理函数中的this对象已被注入为event.currentTarget,因此预先存储)
 29             var slider_instance=this;
 30             //this.slider_content为被滚动的元素
 31             this.slider_content=slider_content;
 32             //this.outer为被滚动元素的父元素
 33             this.outer=slider_content.parentNode;
 34             //创建滑动条
 35             this.slider_bar=createSliderBar();
 36             //创建滑动条块
 37             this.slider_block=createSliderBlock();
 38             //拼装
 39             this.slider_bar.appendChild(this.slider_block);
 40             this.outer.appendChild(this.slider_bar);
 41             //被滚动元素可被滚动的总宽度
 42             this.slider_content_width=this.slider_content.offsetWidth-this.outer.clientWidth;
 43             //滑动条块可滑动的总宽度
 44             this.slider_bar_width=this.slider_bar.clientWidth-this.slider_block.offsetWidth;
 45             //被滚动元素的左边距(相对父元素)
 46             this.slider_content_left=0;
 47             //滚动块的左边距(相对父元素)
 48             this.slider_block_left=0;
 49             //滑动条的左边距(相对视口)
 50             this.slider_bar_pageLeft=getPageLeft(this.slider_bar);
 51             //滑动条块添加鼠标压键事件
 52             this.slider_block.addEventListener("mousedown",mousedownHandler,false);
 53             //离开父元素后取消鼠标移动事件
 54             this.outer.addEventListener("mouseleave",mouseupHandler,false);
 55             //鼠标弹键时取消鼠标移动事件
 56             this.outer.addEventListener("mouseup",mouseupHandler,false);
 57             /**
 58              * 创建滑动条
 59              */
 60             function createSliderBar(){
 61                 var slider_bar=document.createElement("div");
 62                 slider_bar.className="slider_bar";
 63                 return slider_bar;
 64             }
 65             /**
 66              * 创建滑动条块
 67              */
 68             function createSliderBlock(){
 69                 var slider_block=document.createElement("div");
 70                 slider_block.className="slider_block";
 71                 return slider_block
 72             }
 73             /**
 74              * 鼠标按下事件处理
 75              */
 76             function mousedownHandler(event){
 77                 //计算鼠标相对滑动块的左边距,进而在鼠标移动事件处理函数中使用
 78                 //鼠标相对滑动块左边距=鼠标相对视口左边距-滑动块相对视口左边距
 79                 slider_instance.mouseLeft=event.clientX-getPageLeft(this);
 80                 console.log(getPageLeft(this));
 81                 slider_instance.outer.addEventListener("mousemove",mousemoveHandler,false);
 82             }
 83             /**
 84              * 鼠标移动事件处理
 85              */
 86             function mousemoveHandler(event){
 87                 //计算出应当设置的滑动块左边距(相对于父容器)
 88                 //滑动块相对于滑动条左边距=鼠标相对于视口左边距-滑动条相对于视口左边距-鼠标相对于滑动块左边距
 89                 var blockLeft=event.clientX-slider_instance.slider_bar_pageLeft-slider_instance.mouseLeft;
 90                 //如若滑动块相对于父容器左边距大于滑动块可移动宽度或小于0,表示过界;设置为左右界限值
 91                 if(blockLeft>slider_instance.slider_bar_width){
 92                     blockLeft=slider_instance.slider_bar_width
 93                 }else if(blockLeft<0){
 94                     blockLeft=0;
 95                 }
 96                 //设置滑动块的新位置
 97                 slider_instance.slider_block.style.left=blockLeft+"px";
 98                 //按照滚动块已滚动的百分比,设置被滚动元素的marginLeft(负值),进而让其滚动起来
 99                 //被滚动元素的左margin=-(滑动块相对于滑动条左边距/可滑动最大宽度*可滚动元素的最大宽度)
100                 slider_instance.slider_content.style.marginLeft="-"+(blockLeft/slider_instance.slider_bar_width*slider_instance.slider_content_width)+"px";
101             }
102             /**
103              * 鼠标键弹起事件处理
104              */
105             function mouseupHandler(event){
106                 slider_instance.outer.removeEventListener("mousemove",mousemoveHandler,false);
107             }
108             /**
109              * 获得元素的视口左边距
110              */
111             function getPageLeft(el){
112                 var result=el.offsetLeft;
113                 var parent=el.offsetParent;
114                 while(parent!==null){
115                     result+=parent.offsetLeft;
116                     parent=parent.offsetParent;
117                 }
118                 return result;
119             }
120         }
121         //用test_div元素进行展示
122         new Slider(document.getElementsByClassName("test_div")[0]);
123 
124     }
125 </script>
126 <body>
127 <div class="outer">
128     <div class="test_div"></div>
129 </div>
130 </body>
131 </html>

 

以上是关于原生JavaScript实现滚动条的主要内容,如果未能解决你的问题,请参考以下文章

怎么能实现div里的滚动条滚动时有动画效果

原生js实现导航栏吸顶

使用原生javascript实现网页中banner滚动切换效果

JS原生监听滚动条

原生js实现滚动条

如何在 MS Word 文档中显示代码片段,因为它在 *** 中显示(滚动条和灰色背景)