原生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ù)為最大范圍,不傳的話(huà)默認(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給swf傳參數(shù)的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇JS給swf傳參數(shù)的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09
使用 UniApp 實(shí)現(xiàn)小程序的微信登錄功能
這篇文章主要介紹了使用 UniApp 實(shí)現(xiàn)小程序的微信登錄功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
js使用removeChild方法動(dòng)態(tài)刪除div元素
本節(jié)為大家介紹了js使用removeChild方法動(dòng)態(tài)刪除div元素,需要的朋友可以參考下2014-08-08
html5+CSS 實(shí)現(xiàn)禁止IOS長(zhǎng)按復(fù)制粘貼功能
因?yàn)樵谝苿?dòng)端APP需要實(shí)現(xiàn)長(zhǎng)按執(zhí)行別的事件,但是在iOS系統(tǒng)有默認(rèn)的長(zhǎng)按選擇復(fù)制粘貼。禁止在網(wǎng)上找了很多資料,下面小編給大家分享解決方案,一起看看吧2016-12-12
JavaScript高級(jí)函數(shù)應(yīng)用之分時(shí)函數(shù)實(shí)例分析
這篇文章主要介紹了JavaScript高級(jí)函數(shù)應(yīng)用之分時(shí)函數(shù),結(jié)合實(shí)例形式分析了javascript通過(guò)合理分時(shí)函數(shù)應(yīng)用避免瀏覽器卡頓或假死的相關(guān)操作技巧,需要的朋友可以參考下2018-08-08
js 復(fù)制功能 支持 for IE/FireFox/mozilla/ns
js 復(fù)制功能 支持 for IE/FireFox/mozilla/ns...2007-11-11
JavaScript 彈出窗體點(diǎn)擊按鈕返回選擇數(shù)據(jù)的實(shí)現(xiàn)
這兩天一直想實(shí)現(xiàn)這個(gè),以前做做個(gè)Demo,但是不知道跑哪去了。于是今天在網(wǎng)上找了些資料再自己動(dòng)手搞定。廢話(huà)不多說(shuō)。直接進(jìn)入主題啦。2010-04-04

