国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - js教程 - 原生js實現自定義滾動條組件

原生js實現自定義滾動條組件

2022-01-05 17:06蒲公英芽 js教程

這篇文章主要為大家詳細介紹了原生js實現自定義滾動條組件的開發,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了js實現自定義滾動條組件的具體代碼,供大家參考,具體內容如下

功能需求:

1、按照數據結構創建菜單內容,顯示在頁面中;
2、點擊菜單后,顯示對應的下級菜單內容,如果整體內容溢出,則出現滾動條;
3、滾動條的高度要隨著整體內容高度的改變而改變。
4、鼠標拖動滾動條,整體內容要隨著向上滾動。
5、當鼠標滾動時,滾動條和整體內容也要相應滾動。

來看一下效果:

默認狀態:

原生js實現自定義滾動條組件

點擊菜單,內容溢出后,出現滾動條;

原生js實現自定義滾動條組件

鼠標拖動滾動條,整體內容隨著向上滾動:

原生js實現自定義滾動條組件

分析:

  • 這個案例中包括折疊菜單和滾動條兩個組件 ,所以可以分開來寫,然后整合到一起。
  • 折疊菜單中要考慮多級菜單出現的情況,使用遞歸來做,數據的結構一定要統一,方便對數據進行處理。
  • 滾動條的創建中,有兩個比例等式,一是滾動條的高度/外層div高度=外層div高度/整體內容高度;二是滾動條的位置/(外層div高度-滾動條高度)=內容的scrollTop/(整體內容的高度-外層div高度)
  • 當點擊折疊菜單后,需要相應地設置滾動條的高度。折疊菜單是在Menu.js文件中,滾動條的設置是在ScrollBar.js文件中,需要進行拋發、監聽事件。
  • 監聽菜單鼠標滾動的事件,當鼠標滾動時,判斷滾輪方向,設置滾動條和內容的 top 值,也需要用到事件的拋發和監聽。

下面附上代碼:

html結構,模擬數據,創建外層容器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>scrollBar</title>
</head>
<body>
 <script type="module">
 import Utils from './js/Utils.js';
 import Menu from './js/Menu.js';
 import ScrollBar from './js/ScrollBar.js';
 var arr=[
  {name:"A",category:[
  {name:"奧迪",category:[
   {name:"奧迪A3",href:""},
   {name:"奧迪A4L",category:[
   {name:"奧迪A4L-1",href:""}
   ]},
   {name:"奧迪Q3",href:""},
   {name:"奧迪Q5L",href:""},
   {name:"奧迪Q2L",href:""},
   {name:"奧迪Q7(進口)",href:""},
   {name:"奧迪Q8(進口)",href:""},
   {name:"奧迪Q7新能源",href:""},
  ]},
  {name:"阿爾法-羅密歐",category:[
   {name:"Stelvio(進口)",href:""},
   {name:"Giulia(進口)",href:""},
  ]}
  ]},
  {name:"B",category:[
  {name:"奔馳",category:[
   {name:"奔馳C級",href:""},
   {name:"奔馳E級",href:""},
   {name:"奔馳GLA級",href:""},
   {name:"奔馳GLC級",href:""},
   {name:"奔馳A級",href:""},
   {name:"奔馳E級(進口)",href:""},
   {name:"奔馳A級(進口)",href:""},
   {name:"奔馳B級(進口)",href:""},
   {name:"威霆",href:""},
   {name:"奔馳V級",href:""},
  ]},
  {name:"寶馬",category:[
   {name:"寶馬5系",href:""},
   {name:"寶馬1系",href:""},
   {name:"寶馬X1",href:""},
   {name:"寶馬X5(進口)",href:""},
   {name:"寶馬X6(進口)",href:""},
  ]},
  {name:"本田",category:[
   {name:"競瑞",href:""},
   {name:"思域",href:""},
   {name:"本田CR-V",href:""},
   {name:"本田XR-V",href:""},
   {name:"本田UR-V",href:""},
   {name:"艾力紳",href:""},
   {name:"享域",href:""},
   {name:"INSPIRE",href:""},
   {name:"凌派",href:""},
   {name:"雅閣",href:""},
   {name:"繽智",href:""},
  ]},
  {name:"別克",category:[
   {name:"凱越",href:""},
   {name:"英朗",href:""},
   {name:"威朗",href:""},
   {name:"閱朗",href:""},
   {name:"君威",href:""},
   {name:"君越",href:""},
   {name:"昂科拉",href:""},
   {name:"昂科威",href:""},
   {name:"別克GL8",href:""},
   {name:"別克GL6",href:""},
   {name:"VELITE",href:""},
  ]}
  ]}
 ]
 var container;
 init();
 function init(){
  createMenu(arr); 
  createScrollBar();
 }
  function createMenu(arr){
  //創建菜單
  let menu=new Menu(arr);
  //創建最外層容器
  container=Utils.createE("div",{
  width:"235px",
  height:"360px",
  border:"1px solid #ccc",
  position:"relative",
  overflow:"hidden"
  })
  menu.appendTo(container);
  Utils.appendTo(container,"body")
 }
 function createScrollBar(){
  //創建滾動條
  let scrollBar=new ScrollBar(container);
  scrollBar.appendTo(container);
 }
 </script>
</body>
</html>

Menu.js文件,根據數據創建折疊菜單內容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import Utils from './Utils.js';
export default class Menu{
 static SET_BAR_HEIGHT="set_bar_height";
 static MOUSE_WHEEL_EVENT="mouse_wheel_event";
 constructor(_list){
 this.elem=this.createElem(_list);
 }
 createElem(_list){
 if(this.elem) return this.elem;
 //創建最外層ul容器
 let ul=Utils.createE("ul",{
  listStyle:"none",
  padding:"0px",
  margin:"0px",
  width:"235px",
  height:"360px",
  color:"#333",
  fontSize:"14px",
  userSelect: "none",
  position:"absolute"
 });
 //創建li列表
 this.createMenu(_list,ul);
 //ul監聽點擊事件
 ul.addEventListener("click",e=>this.clickHandler(e));
 //ul監聽滾輪事件,火狐使用DOMMouseScroll,其它瀏覽器使用mousewheel
 ul.addEventListener("mousewheel",e=>this.mouseWheelHandler(e));
 ul.addEventListener("DOMMouseScroll",e=>this.mouseWheelHandler(e));
 return ul;
 }
 appendTo(parent){
 Utils.appendTo(this.elem,parent);
 }
 //創建一級菜單
 createMenu(_list,parent){
 for(let i=0;i<_list.length;i++){
  let li=Utils.createE("li",{
  background:"#f5f5f5",
  borderTop:"1px solid #ddd",
  lineHeight:"32px",
  },{
  data:1,//控制一級菜單不能點擊折疊
  })
  let span=Utils.createE("span",{
  marginLeft:"14px",
  fontSize:"18px"
  },{
  textContent:_list[i].name
  })
  Utils.appendTo(span,li);
  Utils.appendTo(li,parent);
  //創建子菜單,第三個參數控制子菜單是否顯示
  this.createSubMenu(_list[i].category,li,0);
 }
 }
 //創建子菜單
 createSubMenu(_subList,_parent,_index){
 //如果沒有子菜單,則跳出
 if(_subList.length===0) return;
 let subUl=Utils.createE("ul",{
  listStyle:"none",
  background:"#fff",
  padding:"0px",
  margin:"0px",
  fontSize:"14px",
  display:_index===0? "block" : "none"
 })
 for(let i=0;i<_subList.length;i++){
  let subLi=Utils.createE("li",{
  paddingLeft:"40px",
  position:"relative",
  cursor:"pointer"
  })
  if(!_subList[i].category){
  //如果當前菜單沒有子菜單,則創建a標簽,進行跳轉
  let subA=Utils.createE("a",{
   color:"#333",
   textDecoration:"none",
   width:"100%",
   display:"inline-block"
  },{
   textContent:_subList[i].name,
   href:_subList[i].href || "javascript:void(0)",
   target:_subList[i].href ? "_blank" : "_self"
  })
  Utils.appendTo(subA,subLi);
  }else{
  //如果當前菜單有子菜單,創建span標簽
  let subSpan=Utils.createE("span",{
   position:"absolute",
   left:"20px",
   top:"8px",
   border: "1px solid #ccc",
   display: "inline-block",
   width: "10px",
   height: "10px",
   lineHeight:"8px"
  },{
   textContent:_subList[i].category.length>0? "+" : "-"
  })
  subLi.textContent=_subList[i].name;
  Utils.appendTo(subSpan,subLi);
  }
  Utils.appendTo(subLi,subUl);
  //如果當前菜單沒有子菜單,則跳過下面的執行
  if(!_subList[i].category) continue;
  //將當前菜單的子菜單作為參數,進行遞歸
  this.createSubMenu(_subList[i].category,subLi,1);
 }
 Utils.appendTo(subUl,_parent);
 }
 clickHandler(e){
 //如果當前點擊的不是li標簽或者span,直接跳出
 if(e.target.nodeName!=="LI" && e.target.nodeName!=="SPAN") return;
 let targ;
 if(e.target.nodeName==="SPAN") targ=e.target.parentElement;
 else targ=e.target;
 //如果當前點擊Li下面沒有子菜單,直接跳出
 if(targ.children.length<=1) return;
 //如果當前點擊的是一級菜單,直接跳出
 if(targ.data===1) return;
 //控制當前點擊的Li下的ul顯示隱藏
 if(!targ.bool) targ.lastElementChild.style.display="block";
 else targ.lastElementChild.style.display="none";
 targ.bool=!targ.bool;
 //改變span標簽的內容
 this.changeSpan(targ);
 //拋發事件,改變滾動條的高度
 var evt=new Event(Menu.SET_BAR_HEIGHT);
 document.dispatchEvent(evt)
 }
 changeSpan(elem){
 if(elem.lastElementChild.style.display==="block"){
  elem.firstElementChild.textContent="-";
 }else{
  elem.firstElementChild.textContent="+";
 }
 }
 mouseWheelHandler(e){
 //阻止事件冒泡
 e.stopPropagation();
 //火狐瀏覽器判斷e.detail,e.detail<0時,表示滾輪往下,頁面往上
 let tag=e.detail,wheelDir;
 //其他瀏覽器判斷e.deltaY,e.deltaY<0時,表示滾輪往下,頁面往上
 if(tag===0) tag=e.deltaY;
 
 if(tag>0){
  //滾輪往下滾動,頁面往上走
  wheelDir="down";
 }else{
  wheelDir="up";
 }
 //拋發事件,將滾輪方向傳遞過去
 let evt=new Event(Menu.MOUSE_WHEEL_EVENT);
 evt.wheelDirection=wheelDir;
 this.elem.dispatchEvent(evt);
 }
}

ScrollBar.js文件,創建滾動條,對滾動條進行操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import Utils from './Utils.js';
import Menu from './Menu.js';
export default class ScrollBar {
 bar;
 conHeight;
 menuHeight;
 wheelSpeed=6;
 barTop=0;
 static SET_BAR_HEIGHT="set_bar_height";
 constructor(parent) {
 this.container = parent;
 this.menuUl=this.container.firstElementChild;
 this.elem = this.createElem();
 //偵聽菜單的點擊事件,動態改變滾動條的高度
 document.addEventListener(ScrollBar.SET_BAR_HEIGHT,()=>this.setBarHeight());
 //ul菜單偵聽滾輪事件
 this.menuUl.addEventListener(Menu.MOUSE_WHEEL_EVENT,e=>this.mouseWheelHandler(e));
 }
 createElem() {
 if (this.elem) return this.elem;
 //創建滾動條的外層容器
 let div = Utils.createE("div", {
  width: "8px",
  height: "100%",
  position: "absolute",
  right: "0px",
  top: "0px",
 })
 this.createBar(div);
 return div;
 }
 appendTo(parent) {
 Utils.appendTo(this.elem,parent);
 }
 createBar(_parent) {
 if(this.bar) return this.bar;
 //創建滾動條
 this.bar = Utils.createE("div", {
  width: "100%",
  position: "absolute",
  left: "0px",
  top: "0px",
  borderRadius: "10px",
  backgroundColor: "rgba(255,0,0,.5)"
 })
 //設置滾動條hover狀態的樣式
 this.bar.addEventListener("mouseenter",e=>this.setMouseStateHandler(e));
 this.bar.addEventListener("mouseleave",e=>this.setMouseStateHandler(e));
 //設置滾動條的高度
 this.setBarHeight();
 //偵聽鼠標拖動事件
 this.mouseHand = e => this.mouseHandler(e);
 this.bar.addEventListener("mousedown", this.mouseHand);
 Utils.appendTo(this.bar, _parent);
 }
 setBarHeight() {
 //外層父容器的高度
 this.conHeight = this.container.clientHeight;
 //實際內容的高度
 this.menuHeight = this.container.firstElementChild.scrollHeight;
 //如果實際內容的高度小于父容器的高度,滾動條隱藏
 if (this.conHeight >= this.menuHeight) this.bar.style.display = "none";
 else this.bar.style.display = "block";
 //計算滾動條的高度
 let h = Math.floor(this.conHeight / this.menuHeight * this.conHeight);
 this.bar.style.height = h + "px";
 }
 setMouseStateHandler(e){
 //設置滾動條hover狀態的樣式
 if(e.type==="mouseenter"){
  this.bar.style.backgroundColor="rgba(255,0,0,1)";
 }else{
  this.bar.style.backgroundColor="rgba(255,0,0,.5)";
 }
 }
 mouseHandler(e) {
 switch (e.type) {
  case "mousedown":
  e.preventDefault();
  this.y = e.offsetY;
  document.addEventListener("mousemove", this.mouseHand);
  document.addEventListener("mouseup", this.mouseHand);
  break;
  case "mousemove":
  //注意:getBoundingClientRect()返回的結果中,width height 都是包含border的
  var rect = this.container.getBoundingClientRect();
  this.barTop = e.clientY - rect.y - this.y;
  //滾動條移動
  this.barMove();
  break;
  case "mouseup":
  document.removeEventListener("mousemove", this.mouseHand);
  document.removeEventListener("mouseup", this.mouseHand);
  break;
 }
 }
 mouseWheelHandler(e){
 //滾輪事件
 if(e.wheelDirection==="down"){
  //滾動往下,菜單內容往上
  this.barTop+=this.wheelSpeed;
 }else{
  this.barTop-=this.wheelSpeed;
 }
 //滾動條移動
 this.barMove();
 }
 barMove(){
 if (this.barTop < 0) this.barTop = 0;
 if (this.barTop > this.conHeight - this.bar.offsetHeight) this.barTop = this.conHeight - this.bar.offsetHeight;
 this.bar.style.top = this.barTop + "px";
 //菜單內容滾動
 this.menuMove();
 }
 menuMove(){
 //計算內容的滾動高度
 let menuTop=this.barTop/(this.conHeight-this.bar.offsetHeight)*(this.menuHeight-this.conHeight);
 this.menuUl.style.top=-menuTop+"px";
 }
}

Utils.js文件,是一個工具包:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
export default class Utils{
 static createE(elem,style,prep){
 elem=document.createElement(elem);
 if(style) for(let prop in style) elem.style[prop]=style[prop];
 if(prep) for(let prop in prep) elem[prop]=prep[prop];
 return elem;
 }
 static appendTo(elem,parent){
 if (parent.constructor === String) parent = document.querySelector(parent);
 parent.appendChild(elem);
 }
 static randomNum(min,max){
 return Math.floor(Math.random*(max-min)+min);
 }
 static randomColor(alpha){
 alpha=alpha||Math.random().toFixed(1);
 if(isNaN(alpha)) alpha=1;
 if(alpha>1) alpha=1;
 if(alpha<0) alpha=0;
 let col="rgba(";
 for(let i=0;i<3;i++){
  col+=Utils.randomNum(0,256)+",";
 }
 col+=alpha+")";
 return col;
 }
 static insertCss(select,styles){
 if(document.styleSheets.length===0){
  let styleS=Utils.createE("style");
  Utils.appendTo(styleS,document.head);
 }
 let styleSheet=document.styleSheets[document.styleSheets.length-1];
 let str=select+"{";
 for(var prop in styles){
  str+=prop.replace(/[A-Z]/g,function(item){
  return "-"+item.toLocaleLowerCase();
  })+":"+styles[prop]+";";
 }
 str+="}"
 styleSheet.insertRule(str,styleSheet.cssRules.length);
 }
 static getIdElem(elem,obj){
 if(elem.id) obj[elem.id]=elem;
 if(elem.children.length===0) return obj;
 for(let i=0;i<elem.children.length;i++){
  Utils.getIdElem(elem.children[i],obj);
 }
 }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/charissa2017/article/details/104098404

延伸 · 閱讀

精彩推薦
  • js教程如何使用原生Js實現隨機點名詳解

    如何使用原生Js實現隨機點名詳解

    這篇文章主要給大家介紹了關于如何使用原生Js實現隨機點名的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習...

    CV_Di8092021-12-27
  • js教程JavaScript實現點擊切換驗證碼及校驗

    JavaScript實現點擊切換驗證碼及校驗

    這篇文章主要為大家詳細介紹了JavaScript實現點擊切換驗證碼及校驗,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    棟棟很優秀啊3622021-12-29
  • js教程JS addEventListener()和attachEvent()方法實現注冊事件

    JS addEventListener()和attachEvent()方法實現注冊事件

    這篇文章主要介紹了JS addEventListener()和attachEvent()方法實現注冊事件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    C語言中文網9572021-12-30
  • js教程基于 Next.js 的 SSR/SSG 方案了解一下?

    基于 Next.js 的 SSR/SSG 方案了解一下?

    服務端渲染(SSR,Server Side Render)與客戶端渲染(CSR,Client Side Render)的核心區分點簡單來說就是完整的 HTML 文檔在服務端還是瀏覽器里組裝完成。...

    DYBOY4492021-12-27
  • js教程基于javascript實現移動端輪播圖效果

    基于javascript實現移動端輪播圖效果

    這篇文章主要為大家詳細介紹了基于javascript實現移動端輪播圖效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    A.香辣雞腿堡8982021-12-15
  • js教程JavaScript實現頁面高亮操作提示和蒙板

    JavaScript實現頁面高亮操作提示和蒙板

    這篇文章主要介紹了JavaScript實現頁面高亮操作提示和蒙板,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    stones4zd5792021-12-24
  • js教程利用JS判斷元素是否為數組的方法示例

    利用JS判斷元素是否為數組的方法示例

    這篇文章主要給大家介紹了關于利用JS判斷元素是否為數組的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價...

    Fahrenheitzz10022021-12-29
  • js教程mapboxgl實現帶箭頭軌跡線的代碼

    mapboxgl實現帶箭頭軌跡線的代碼

    這篇文章主要介紹了mapboxgl實現帶箭頭軌跡線的代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下...

    GIS兵器庫9152021-12-27
主站蜘蛛池模板: 亚洲深深色噜噜狠狠网站 | 精品一区二区三区免费毛片爱 | 精品久久久久久久久久久下田 | 久久精品91久久久久久再现 | 亚洲va欧美va人人爽成人影院 | 成人高清在线 | 成人免费观看高清视频 | 爱色av网 | 伊人福利视频 | 久久一日本道色综合久久 | 97碰碰碰免费公开在线视频 | 日韩一区二区在线观看 | 日本不卡高字幕在线2019 | 在线成人国产 | 羞羞视频免费观 | 丁香伊人 | 在线观看亚洲专区 | 依人九九 | 奇米在线777 | 欧美激情小视频 | 国产精品一区二区久久久 | 一区二区三区视频在线观看 | 国产精品久久久久久久久 | 一级一片免费视频 | 99精品国产一区二区青青牛奶 | 九色 在线 | 国产露脸国语对白在线 | 99视频这里有精品 | 凹凸国产成人精品视频免费 | 亚洲一区电影 | 99视频免费| 亚洲欧美激情精品一区二区 | 美日韩一区 | 国产亚洲精品久久久闺蜜 | 精品久久久久久 | 亚洲综合激情网 | 亚洲视频天堂 | 在线国产视频 | 都市激情在线视频 | 久久精品国产清自在天天线 | 欧美精品一区二区三区在线播放 |