原生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

回到顶部