本文实例为大家分享了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);
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/Charissa2017/article/details/104099156