原生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实现滚动条的主要内容,如果未能解决你的问题,请参考以下文章