教你用原生JS写一个滑块组件
Admin 2021-04-17 群英技术资讯 2033 次浏览
滑块组件就是一个允许用户在有限区间内通过移动滑块来选择值的组件。滑块组件的应用是比较常见的,例如商品价格区间筛选,音量设置,滑块验证等等。这篇文章就给大家介绍一下用原生JS实现滑块组件,下面是实现效果,功能分析以及代码。
1、最小值为0,按照给定的最大值,生成区间范围;
2、拖动滑块移动时,显示相应的范围区间,滑块条显示对应的状态;
3、点击时,使最近的滑块移动到鼠标点击的位置。

当拖动滑块时,显示如下:

下面附上代码:
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实现Js滑块组件的介绍,滑块组件可以实现的效果是很多,大家可以参考上述代码自己来动手实现一下。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章给大家分享的是JavaScript中位运算符。小编觉得挺实用的,因此分享给大家做个参考。JavaScript中的有7种位运算符,文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来我们一起来看看它们的使用。
这篇文章主要为大家详细介绍了vue大屏展示适配,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章介绍了ASP.NET实现Repeater控件数据绑定的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
这篇文章主要为大家详细介绍了JavaScript实现抽奖器效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本篇文章给大家带来了关于javascript的相关知识,其中主要整理了Number对象的相关问题,Number 对象是原始数值的包装对象,Number 创建方式 new Number(),下面一起来看一下,希望对大家有帮助。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008