原生js實現(xiàn)滑塊區(qū)間組件
本文實例為大家分享了js實現(xiàn)滑塊區(qū)間組件的具體代碼,供大家參考,具體內(nèi)容如下
功能需求:
1、最小值為0,按照給定的最大值,生成區(qū)間范圍;
2、拖動滑塊移動時,顯示相應(yīng)的范圍區(qū)間,滑塊條顯示對應(yīng)的狀態(tài);
3、點擊時,使最近的滑塊移動到鼠標(biāo)點擊的位置。
默認效果:
當(dāng)拖動滑塊時,顯示如下:
分析:
- 首先布局要寫好,一共有4個元素,兩個滑塊和兩個滑塊條。布局時要考慮到后期對滑塊和滑塊條進行事件監(jiān)聽,盡可能少地出現(xiàn)事件冒泡;
- 拖動滑塊時,要區(qū)分是左邊的滑塊還是右邊的滑塊;
- 鼠標(biāo)的click事件和mousedown事件要兼容好,這里統(tǒng)一使用的是mousedown事件;
- 要確定好左右滑塊的最大最小 left 值;
- 滑塊條的顯示就很簡單了,寬度是左、右滑塊的定位差值,left值是左滑塊的left值;
- 因為使用了事件委托機制,而在mousemove和mouseup事件中,無法判斷當(dāng)前操作的是哪一個滑塊,所以要在鼠標(biāo)按下時,將當(dāng)前操作的對象傳到mousemove事件中;
下面附上代碼:
html結(jié)構(gòu),實例化滑塊,可以設(shè)置當(dāng)前滑塊的區(qū)間范圍:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>slide</title> </head> <body> <script type="module"> import Slide from "./js/Slide.js"; init(); function init(){ //參數(shù)為最大范圍,不傳的話默認是4000 let slide=new Slide(4200); slide.appendTo("body"); } </script> </body> </html>
Slide.js文件:完成創(chuàng)建滑塊,拖動滑塊,點擊滑塊的功能。
import Utils from "./Utils.js"; export default class Slide{ static styleCss=false; //最小范圍 minNum=0; //最大范圍 maxNum; //左邊按鈕的left值 leftBtnLeft=0; //右邊按鈕的left值 rightBtnLeft=238; constructor(_max=4000){ //最大值默認為4000 this.maxNum=_max; this.elem=this.createElem(); } createElem(){ if(this.elem) return this.elem; //創(chuàng)建最外層容器 let div=Utils.createE("div"); div.className="slideContainer"; div.innerHTML=`<p class="priceTxt">價格<span id="rangeText">¥${this.minNum}-${this.maxNum}</span></p> <div class="rangeContainer" id="rangeContainer"> <div class="bgRange" id="bgRange"></div> <div class="priceRange" id="priceRange"></div> <span id="leftBtn" class="leftBtn"></span> <span id="rightBtn" class="rightBtn"></span> </div>`; Utils.getIdElem(div,this); //設(shè)置樣式 Slide.setStyles(); //給父元素監(jiān)聽mousedown事件 this.rangeContainer.addEventListener("mousedown",e=>this.mouseHandler(e)) return div; } appendTo(parent){ Utils.appendTo(this.elem,parent); } mouseHandler(e){ //注意:getBoundingClientRect()返回的結(jié)果中,width height 都是包含border的 let rect=this.rangeContainer.getBoundingClientRect(); switch (e.type) { case "mousedown": //取消鼠標(biāo)快速拖動的默認事件 e.preventDefault(); this.x = e.offsetX; this.btnType=e.target.id; //如果點擊的是背景條,執(zhí)行rangeClick函數(shù) if(/Range/.test(this.btnType)){ e.stopPropagation(); //點擊函數(shù) this.rangeClick(e); return; } //如果點擊的是按鈕,監(jiān)聽document鼠標(biāo)移動事件 this.mouseHandlers=e=>this.mouseHandler(e); document.addEventListener("mousemove", this.mouseHandlers); document.addEventListener("mouseup", this.mouseHandlers); break; case "mousemove": let x = e.clientX - rect.x - this.x; //獲取左右按鈕的left值 this.leftBtnLeft=parseInt(getComputedStyle(this.leftBtn).left); this.rightBtnLeft=parseInt(getComputedStyle(this.rightBtn).left); if (this.btnType === "leftBtn") { //確定左邊按鈕的取值范圍 if (x < 0) x = 0; if (x > this.rightBtnLeft) x = this.rightBtnLeft; this.leftBtn.style.left = x + "px"; } else if (this.btnType === "rightBtn") { //確定右邊按鈕的取值范圍,減去1px邊框 if (x < this.leftBtnLeft) x = this.leftBtnLeft; if (x > this.bgRange.offsetWidth - 2) x = this.bgRange.offsetWidth - 2; this.rightBtn.style.left = x + "px"; } //文字范圍顯示 this.changeRangeText(); break; case "mouseup": //移動事件監(jiān)聽 document.removeEventListener("mousemove", this.mouseHandlers); document.removeEventListener("mouseup", this.mouseHandlers); break; } } rangeClick(e){ //計算出鼠標(biāo)點擊位置的值 let click_X=e.clientX-this.rangeContainer.getBoundingClientRect().x-this.leftBtn.offsetWidth/2; //判斷,如果當(dāng)前點擊的位置是在左邊按鈕的左側(cè)、或者當(dāng)左右按鈕重疊時,點擊的位置在按鈕左側(cè),讓左邊按鈕移動到鼠標(biāo)點擊的位置 if(Math.abs(click_X-this.leftBtnLeft)<Math.abs(click_X-this.rightBtnLeft) || (this.leftBtnLeft===this.rightBtnLeft && click_X<this.leftBtnLeft)) this.leftBtn.style.left=click_X+"px"; //否則,讓右邊按鈕移動到鼠標(biāo)點擊的位置 else this.rightBtn.style.left=click_X+"px"; //獲取移動后的左右按鈕的left值 this.leftBtnLeft=parseInt(getComputedStyle(this.leftBtn).left); this.rightBtnLeft=parseInt(getComputedStyle(this.rightBtn).left); //文字范圍顯示 this.changeRangeText(); } changeRangeText(){ //計算出最小范圍與最大范圍的值,四舍五入 let minTxt=Math.round(this.leftBtnLeft/(this.bgRange.clientWidth-2)*this.maxNum); let maxTxt=Math.round(this.rightBtnLeft/(this.bgRange.clientWidth-2)*this.maxNum); this.rangeText.innerText=`¥${minTxt}-${maxTxt}`; //滑塊顏色的改變 this.changeRangeSlide(); } changeRangeSlide(){ //滑塊寬度等于左右按鈕間的距離 this.priceRange.style.width=this.rightBtnLeft-this.leftBtnLeft+"px"; //滑塊的left值等于左邊按鈕的left值 this.priceRange.style.left=this.leftBtnLeft+"px"; } static setStyles(){ if(Slide.styleCss) return; Slide.styleCss=true; Utils.insertCss(".slideContainer",{ width:"260px", height:"70px", margin:"50px" }) Utils.insertCss(".priceTxt",{ fontSize:"14px", color:"#666", marginBottom:"20px" }) Utils.insertCss(".priceTxt span",{ float:"right" }) Utils.insertCss(".rangeContainer",{ width:"260px", height:"20px", position:"relative", }) Utils.insertCss(".bgRange",{ width:"240px", height:"3px", backgroundColor:"#dedede", position:"absolute", left:"10px", top:"9px" }) Utils.insertCss(".priceRange",{ width:"240px", height:"3px", background:"#ffa800", position:"absolute", left:"10px", top:"9px" }) Utils.insertCss(".rangeContainer span",{ width: "20px", height: "20px", borderRadius:"50%", border:"1px solid #ccc", background:"#fff", position:"absolute", top:"0px", boxShadow:"2px 2px 2px #333" }) Utils.insertCss(".leftBtn",{ left:"0px" }) Utils.insertCss(".rightBtn",{ left:"238px" }) } }
Utils.js文件:是一個工具包文件。
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); } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue 實現(xiàn)拖動滑塊驗證功能(只有css+js沒有后臺驗證步驟)
- 基于JS組件實現(xiàn)拖動滑塊驗證功能(代碼分享)
- 基于JavaScript實現(xiàn)拖動滑塊效果
- Javascript實現(xiàn)滑塊滑動改變值的實現(xiàn)代碼
- js實現(xiàn)兼容PC端和移動端滑塊拖動選擇數(shù)字效果
- JS響應(yīng)鼠標(biāo)點擊實現(xiàn)兩個滑塊區(qū)間拖動效果
- js用拖動滑塊來控制圖片大小的方法
- 基于Vue.js實現(xiàn)tab滑塊效果
- Javascript 鼠標(biāo)移動上去小三角形滑塊緩慢跟隨效果
- JS實現(xiàn)網(wǎng)頁游戲中滑塊響應(yīng)鼠標(biāo)點擊移動效果
相關(guān)文章
js實現(xiàn)省級聯(lián)動(數(shù)據(jù)結(jié)構(gòu)優(yōu)化)
這篇文章主要為大家詳細介紹了js實現(xiàn)省級聯(lián)動,數(shù)據(jù)結(jié)構(gòu)優(yōu)化,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-07-07JavaScript/TypeScript 實現(xiàn)并發(fā)請求控制的示例代碼
這篇文章主要介紹了JavaScript/TypeScript 實現(xiàn)并發(fā)請求控制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01JavaScript中判斷整數(shù)的多種方法總結(jié)
這篇文章主要介紹了JavaScript中判斷整數(shù)的多種方法總結(jié),本文總結(jié)了5種判斷整數(shù)的方法,如取余運算符判斷、Math.round、Math.ceil、Math.floor判斷等,需要的朋友可以參考下2014-11-11如何在面試中手寫出javascript節(jié)流和防抖函數(shù)
這篇文章主要介紹了如何在面試中手寫出javascript節(jié)流和防抖函數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10