原生JavaScript實現滾動條

沒事找事,明明overflow:scroll|auto就能夠,只是難看點(實際上css也能設置)。只當練習寫拖拽、監聽事件、位置檢測了。javascript

原理是對滑動條塊進行監聽,按下鼠標按鍵後,監聽鼠標移動,而後根據滑動條塊移動的百分比算出滾動區域的滾動程度,用marginLeft進行滾動。具體的寫在註釋裏。css

總體弄成了一個對象,防止各類亂七八糟的數據污染全局變量。另外,對象內部調用的函數也都寫到了對象構造函數的裏面,因爲對象做用域鏈的原理,外部沒法進行調用,防止不當心在外部調用。html

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title>A demo</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>
相關文章
相關標籤/搜索