原生JavaScript實現滾動條

来源:http://www.cnblogs.com/Kokukiyo/archive/2016/01/23/5154186.html
-Advertisement-
Play Games

原生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>

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有時候面試的時候,面試官會問靜態方法里能不能調用非靜態方法,這時候呢,你的回答是什麼呢?雖然不能直接調用,但是可以間接的調用,可以通過將一個對象的引用傳入靜態方法中,再去調用該對象的非靜態方法。靜態方法通過用傳進來的對象引用調用非靜態方法,從而達到靜態方法調用非靜態方法。 1 public clas...
  • hi之前有將近兩周的時間沒有更新,除了懶就是其他的事情耽誤了。現在好了,回家了,雖然家裡停水,外面又有積雪,天寒地凍的,但諸多不便,都比不過有點閑的好。開搞每個學PHP的必經之路——電商網站的開發。1、電商網站開發——前端一、首頁製作1.1 概況&準備整個電商網站包括什麼呢,就是首頁信息,後面的.....
  • 對C++的指針總覺得和引用差不多,其實還是挺有差別的。程式先看一個小程式: int a = 1; int& ra = a; int* pa = &ra; printf("&a = %02X\n", &a); //3EFCD0<< printf("a = %d\n", a...
  • C++Primer第5版學習筆記(二)第三章的重難點內容 你可以點擊這裡回顧第一、二章的內容 這篇文章只是C++初學者的學習筆記...。書接前文,第三章主要講這麼五個概念: 1.using聲明,我知道挺多同學寫代碼練手都要在源文件前幾句直接加using namespace std;然而us...
  • 策略模式在實際工作中我用到了策略模式,但為什麼要有環境角色呢?這裡我貼上英文對含義的介紹,The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable....
  • jQuery form插件的使用--使用 fieldValue 方法校驗表單. Demo 7 : jQuery form插件的使用--使用 fieldValue 方法校驗表單. 名稱: 地址: ...
  • 1,HTML全稱Hyper Text Markup Language(超文本標記語言)擴展XML:Extendsible Markup Language(可擴展性標記語言)2,CSS是一種表現樣式3,js則是一種行為,控制網頁的行為。編寫html 文檔的註意點01.所有標簽字母均小寫。02.有開始就...
  • 數組的方法:array.concat 一個數組去連接另一個數組,返回一個合成數組。var arrC=arrA.concat(arrB,'asd','sad',true,1.5);array.join 將數組用指定符號連接為一個字元串,並返回這個字元串。比用+快很多。var strA=arrA...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...