原生js实现滑块区间组件
本文实例为大家分享了js实现滑块区间组件的具体代码,供大家参考,具体内容如下
功能需求:
1、最小值为0,按照给定的最大值,生成区间范围;
2、拖动滑块移动时,显示相应的范围区间,滑块条显示对应的状态;
3、点击时,使最近的滑块移动到鼠标点击的位置。
默认效果:
当拖动滑块时,显示如下:
分析:
- 首先布局要写好,一共有4个元素,两个滑块和两个滑块条。布局时要考虑到后期对滑块和滑块条进行事件监听,尽可能少地出现事件冒泡;
- 拖动滑块时,要区分是左边的滑块还是右边的滑块;
- 鼠标的click事件和mousedown事件要兼容好,这里统一使用的是mousedown事件;
- 要确定好左右滑块的最大最小 left 值;
- 滑块条的显示就很简单了,宽度是左、右滑块的定位差值,left值是左滑块的left值;
- 因为使用了事件委托机制,而在mousemove和mouseup事件中,无法判断当前操作的是哪一个滑块,所以要在鼠标按下时,将当前操作的对象传到mousemove事件中;
下面附上代码:
html结构,实例化滑块,可以设置当前滑块的区间范围:
<!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(){
//参数为最大范围,不传的话默认是4000
let slide=new Slide(4200);
slide.appendTo("body");
}
</script>
</body>
</html>
Slide.js文件:完成创建滑块,拖动滑块,点击滑块的功能。
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;
//创建最外层容器
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);
//设置样式
Slide.setStyles();
//给父元素监听mousedown事件
this.rangeContainer.addEventListener("mousedown",e=>this.mouseHandler(e))
return div;
}
appendTo(parent){
Utils.appendTo(this.elem,parent);
}
mouseHandler(e){
//注意:getBoundingClientRect()返回的结果中,width height 都是包含border的
let rect=this.rangeContainer.getBoundingClientRect();
switch (e.type) {
case "mousedown":
//取消鼠标快速拖动的默认事件
e.preventDefault();
this.x = e.offsetX;
this.btnType=e.target.id;
//如果点击的是背景条,执行rangeClick函数
if(/Range/.test(this.btnType)){
e.stopPropagation();
//点击函数
this.rangeClick(e);
return;
}
//如果点击的是按钮,监听document鼠标移动事件
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":
//移动事件监听
document.removeEventListener("mousemove", this.mouseHandlers);
document.removeEventListener("mouseup", this.mouseHandlers);
break;
}
}
rangeClick(e){
//计算出鼠标点击位置的值
let click_X=e.clientX-this.rangeContainer.getBoundingClientRect().x-this.leftBtn.offsetWidth/2;
//判断,如果当前点击的位置是在左边按钮的左侧、或者当左右按钮重叠时,点击的位置在按钮左侧,让左边按钮移动到鼠标点击的位置
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";
//否则,让右边按钮移动到鼠标点击的位置
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);
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
以上是 原生js实现滑块区间组件 的全部内容, 来源链接: utcz.com/p/219432.html