原生js实现滑块区间组件


Posted in Javascript onJanuary 20, 2021

本文实例为大家分享了js实现滑块区间组件的具体代码,供大家参考,具体内容如下

功能需求:

1、最小值为0,按照给定的最大值,生成区间范围;
2、拖动滑块移动时,显示相应的范围区间,滑块条显示对应的状态;
3、点击时,使最近的滑块移动到鼠标点击的位置。

默认效果:

原生js实现滑块区间组件

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

原生js实现滑块区间组件

分析:

  • 首先布局要写好,一共有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);
 }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery图片上下tab切换效果
Mar 18 Javascript
jquery制作弹窗提示窗口代码分享
Mar 02 Javascript
30个经典的jQuery代码开发技巧
Dec 15 Javascript
jQuery中 prop() attr()使用详解
May 19 Javascript
使用jQuery给input标签设置默认值
Jun 20 Javascript
深入理解ES6之数据解构的用法
Jan 13 Javascript
ES6 Object方法扩展的应用实例分析
Jun 25 Javascript
JS实现横向轮播图(初级版)
Jun 24 Javascript
vue下canvas裁剪图片实例讲解
Apr 16 Javascript
JS删除数组指定值常用方法详解
Jun 04 Javascript
在Vue中获取自定义属性方法:data-id的实例
Sep 09 Javascript
js实现弹窗猜数字游戏
Nov 26 Javascript
原生js实现下拉框选择组件
Jan 20 #Javascript
原生js实现自定义滚动条组件
Jan 20 #Javascript
原生js实现自定义滚动条
Jan 20 #Javascript
uniapp微信小程序:key失效的解决方法
Jan 20 #Javascript
JavaScript实现下拉列表
Jan 20 #Javascript
浅谈Vue开发人员的7个最好的VSCode扩展
Jan 20 #Vue.js
详解实现vue的数据响应式原理
Jan 20 #Vue.js
You might like
php 把数字转换成汉字的代码
2015/07/21 PHP
详解Yii实现分页的两种方法
2017/01/14 PHP
PHP封装的多文件上传类实例与用法详解
2017/02/07 PHP
ThinkPHP 3.2.2实现事务操作的方法
2017/05/05 PHP
PHP实现对xml进行简单的增删改查(CRUD)操作示例
2017/05/19 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
php服务器的系统详解
2019/10/12 PHP
jQuery 获取对象 基本选择与层级
2010/05/31 Javascript
javascript深入理解js闭包
2010/07/03 Javascript
jQuery链式操作如何实现以及为什么要用链式操作
2013/01/17 Javascript
用jQuery获取IE9下拉框默认值问题探讨
2013/07/22 Javascript
js数字转换为float,取N位小数
2014/02/08 Javascript
使用jquery解析XML示例代码
2014/09/05 Javascript
微信小程序 页面传参实例详解
2016/11/16 Javascript
vue中axios处理http发送请求的示例(Post和get)
2017/10/13 Javascript
jquery实现侧边栏左右伸缩效果的示例
2017/12/19 jQuery
Angular4学习之Angular CLI的安装与使用教程
2018/01/04 Javascript
JavaScript创建对象方法实例小结
2018/09/03 Javascript
Vuex的基本概念、项目搭建以及入坑点
2018/11/04 Javascript
使用Python对微信好友进行数据分析
2018/06/27 Python
Python3转换html到pdf的不同解决方案
2019/03/11 Python
选择python进行数据分析的理由和优势
2019/06/25 Python
Django 源码WSGI剖析过程详解
2019/08/05 Python
python @classmethod 的使用场合详解
2019/08/23 Python
Python3 合并二叉树的实现
2019/09/30 Python
解决Tensorboard可视化错误:不显示数据 No scalar data was found
2020/02/15 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
Python如何对XML 解析
2020/06/28 Python
python如何建立全零数组
2020/07/19 Python
CSS3实现div从下往上滑入滑出效果示例
2020/04/28 HTML / CSS
html5使用canvas绘制太阳系效果
2014/12/15 HTML / CSS
eBay澳大利亚站:eBay.com.au
2018/02/02 全球购物
如何启动时不需输入用户名与密码
2014/05/09 面试题
投资意向书
2014/07/30 职场文书
办公室主任个人对照检查材料思想汇报
2014/10/11 职场文书
初中差生评语
2014/12/29 职场文书