原生js實(shí)現(xiàn)滑塊區(qū)間組件
本文實(shí)例為大家分享了js實(shí)現(xiàn)滑塊區(qū)間組件的具體代碼,供大家參考,具體內(nèi)容如下
功能需求:
1、最小值為0,按照給定的最大值,生成區(qū)間范圍;
2、拖動(dòng)滑塊移動(dòng)時(shí),顯示相應(yīng)的范圍區(qū)間,滑塊條顯示對(duì)應(yīng)的狀態(tài);
3、點(diǎn)擊時(shí),使最近的滑塊移動(dòng)到鼠標(biāo)點(diǎn)擊的位置。
默認(rèn)效果:
當(dāng)拖動(dòng)滑塊時(shí),顯示如下:
分析:
- 首先布局要寫(xiě)好,一共有4個(gè)元素,兩個(gè)滑塊和兩個(gè)滑塊條。布局時(shí)要考慮到后期對(duì)滑塊和滑塊條進(jìn)行事件監(jiān)聽(tīng),盡可能少地出現(xiàn)事件冒泡;
- 拖動(dòng)滑塊時(shí),要區(qū)分是左邊的滑塊還是右邊的滑塊;
- 鼠標(biāo)的click事件和mousedown事件要兼容好,這里統(tǒng)一使用的是mousedown事件;
- 要確定好左右滑塊的最大最小 left 值;
- 滑塊條的顯示就很簡(jiǎn)單了,寬度是左、右滑塊的定位差值,left值是左滑塊的left值;
- 因?yàn)槭褂昧耸录袡C(jī)制,而在mousemove和mouseup事件中,無(wú)法判斷當(dāng)前操作的是哪一個(gè)滑塊,所以要在鼠標(biāo)按下時(shí),將當(dāng)前操作的對(duì)象傳到mousemove事件中;
下面附上代碼:
html結(jié)構(gòu),實(shí)例化滑塊,可以設(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ù)為最大范圍,不傳的話默認(rèn)是4000 let slide=new Slide(4200); slide.appendTo("body"); } </script> </body> </html>
Slide.js文件:完成創(chuàng)建滑塊,拖動(dòng)滑塊,點(diǎn)擊滑塊的功能。
import Utils from "./Utils.js"; export default class Slide{ static styleCss=false; //最小范圍 minNum=0; //最大范圍 maxNum; //左邊按鈕的left值 leftBtnLeft=0; //右邊按鈕的left值 rightBtnLeft=238; constructor(_max=4000){ //最大值默認(rèn)為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">價(jià)格<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)聽(tīng)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)快速拖動(dòng)的默認(rèn)事件 e.preventDefault(); this.x = e.offsetX; this.btnType=e.target.id; //如果點(diǎn)擊的是背景條,執(zhí)行rangeClick函數(shù) if(/Range/.test(this.btnType)){ e.stopPropagation(); //點(diǎn)擊函數(shù) this.rangeClick(e); return; } //如果點(diǎn)擊的是按鈕,監(jiān)聽(tīng)document鼠標(biāo)移動(dòng)事件 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": //移動(dòng)事件監(jiān)聽(tīng) document.removeEventListener("mousemove", this.mouseHandlers); document.removeEventListener("mouseup", this.mouseHandlers); break; } } rangeClick(e){ //計(jì)算出鼠標(biāo)點(diǎn)擊位置的值 let click_X=e.clientX-this.rangeContainer.getBoundingClientRect().x-this.leftBtn.offsetWidth/2; //判斷,如果當(dāng)前點(diǎn)擊的位置是在左邊按鈕的左側(cè)、或者當(dāng)左右按鈕重疊時(shí),點(diǎn)擊的位置在按鈕左側(cè),讓左邊按鈕移動(dòng)到鼠標(biāo)點(diǎn)擊的位置 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"; //否則,讓右邊按鈕移動(dòng)到鼠標(biāo)點(diǎn)擊的位置 else this.rightBtn.style.left=click_X+"px"; //獲取移動(dòng)后的左右按鈕的left值 this.leftBtnLeft=parseInt(getComputedStyle(this.leftBtn).left); this.rightBtnLeft=parseInt(getComputedStyle(this.rightBtn).left); //文字范圍顯示 this.changeRangeText(); } changeRangeText(){ //計(jì)算出最小范圍與最大范圍的值,四舍五入 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文件:是一個(gè)工具包文件。
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); } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue 實(shí)現(xiàn)拖動(dòng)滑塊驗(yàn)證功能(只有css+js沒(méi)有后臺(tái)驗(yàn)證步驟)
- 基于JS組件實(shí)現(xiàn)拖動(dòng)滑塊驗(yàn)證功能(代碼分享)
- 基于JavaScript實(shí)現(xiàn)拖動(dòng)滑塊效果
- Javascript實(shí)現(xiàn)滑塊滑動(dòng)改變值的實(shí)現(xiàn)代碼
- js實(shí)現(xiàn)兼容PC端和移動(dòng)端滑塊拖動(dòng)選擇數(shù)字效果
- JS響應(yīng)鼠標(biāo)點(diǎn)擊實(shí)現(xiàn)兩個(gè)滑塊區(qū)間拖動(dòng)效果
- js用拖動(dòng)滑塊來(lái)控制圖片大小的方法
- 基于Vue.js實(shí)現(xiàn)tab滑塊效果
- Javascript 鼠標(biāo)移動(dòng)上去小三角形滑塊緩慢跟隨效果
- JS實(shí)現(xiàn)網(wǎng)頁(yè)游戲中滑塊響應(yīng)鼠標(biāo)點(diǎn)擊移動(dòng)效果
相關(guān)文章
js實(shí)現(xiàn)省級(jí)聯(lián)動(dòng)(數(shù)據(jù)結(jié)構(gòu)優(yōu)化)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)省級(jí)聯(lián)動(dòng),數(shù)據(jù)結(jié)構(gòu)優(yōu)化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07JavaScript/TypeScript 實(shí)現(xiàn)并發(fā)請(qǐng)求控制的示例代碼
這篇文章主要介紹了JavaScript/TypeScript 實(shí)現(xiàn)并發(fā)請(qǐng)求控制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01JavaScript中判斷整數(shù)的多種方法總結(jié)
這篇文章主要介紹了JavaScript中判斷整數(shù)的多種方法總結(jié),本文總結(jié)了5種判斷整數(shù)的方法,如取余運(yùn)算符判斷、Math.round、Math.ceil、Math.floor判斷等,需要的朋友可以參考下2014-11-11用js提交表單解決一個(gè)頁(yè)面有多個(gè)提交按鈕的問(wèn)題
這篇文章主要介紹了用js提交表單解決一個(gè)頁(yè)面有多個(gè)提交按鈕的問(wèn)題,主要是判斷是否為提交文本,然后再執(zhí)行相應(yīng)的動(dòng)作,需要的朋友可以參考下2014-09-09如何在面試中手寫(xiě)出javascript節(jié)流和防抖函數(shù)
這篇文章主要介紹了如何在面試中手寫(xiě)出javascript節(jié)流和防抖函數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10js 鍵盤(pán)記錄實(shí)現(xiàn)(兼容FireFox和IE)
用js實(shí)現(xiàn)鍵盤(pán)記錄,要關(guān)注瀏覽器的三種按鍵事件類(lèi)型,即keydown,keypress和keyup,它們分別對(duì)應(yīng)onkeydown、onkeypress和onkeyup這三個(gè)事件句柄。一個(gè)典型的按鍵會(huì)產(chǎn)生所有這三種事件,依次是keydown,keypress,然后是按鍵釋放時(shí)候的keyup。2010-02-02