原生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 相关文章推荐
javascript:以前写的xmlhttp池,代码
May 18 Javascript
JavaScript 实现模态对话框 源代码大全
May 02 Javascript
基于JQuery实现鼠标点击文本框显示隐藏提示文本
Feb 23 Javascript
浅谈javascript实现八大排序
Apr 27 Javascript
jQuery中iframe的操作(点击按钮新增窗口)
Apr 20 Javascript
jquery dialog获取焦点的方法
Feb 09 Javascript
jquery实现提示语淡入效果
May 05 jQuery
ionic 3.0+ 项目搭建运行环境的教程
Aug 09 Javascript
Vue 自定义动态组件实例详解
Mar 28 Javascript
es6数据变更同步到视图层的方法
Mar 04 Javascript
js实现全选反选不选功能代码详解
Apr 24 Javascript
微信小程序 自定义弹窗实现过程(附代码)
Dec 05 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 for 循环语句使用方法详细说明
2010/05/09 PHP
php自定义apk安装包实例
2014/10/20 PHP
php以post形式发送xml的方法
2014/11/04 PHP
PHP中SimpleXML函数用法分析
2014/11/26 PHP
Smarty最简单实现列表奇偶变色的方法
2015/07/01 PHP
splice slice区别
2006/10/09 Javascript
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
javascript获取作用在元素上面的样式属性代码
2012/09/20 Javascript
js返回上一页并刷新代码整理
2012/12/21 Javascript
jquery遍历筛选数组的几种方法和遍历解析json对象
2013/12/13 Javascript
js实现使用鼠标拖拽切换图片的方法
2015/05/04 Javascript
在AngularJS框架中处理数据建模的方式解析
2016/03/05 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
2016/06/23 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
2016/07/25 Javascript
浅析JavaScript的几种Math函数,random(),ceil(),round(),floor()
2016/12/22 Javascript
详解使用React全家桶搭建一个后台管理系统
2017/11/04 Javascript
JavaScript框架Angular和React深度对比
2017/11/20 Javascript
vue中的watch监听数据变化及watch中各属性的详解
2018/09/11 Javascript
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
对vue中的事件穿透与禁止穿透实例详解
2019/10/28 Javascript
浅谈如何优雅处理JavaScript异步错误
2019/11/12 Javascript
Nodejs在局域网配置https访问的实现方法
2020/10/17 NodeJs
分析并输出Python代码依赖的库的实现代码
2015/08/09 Python
Python爬虫爬取美剧网站的实现代码
2016/09/03 Python
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
python 反编译exe文件为py文件的实例代码
2019/06/27 Python
PowerBI和Python关于数据分析的对比
2019/07/11 Python
使用django的ORM框架按月统计近一年内的数据方法
2019/07/18 Python
python 将视频 通过视频帧转换成时间实例
2020/04/23 Python
详解Python中的编码问题(encoding与decode、str与bytes)
2020/09/30 Python
Square Off美国/加拿大:世界上最聪明的国际象棋棋盘
2018/12/06 全球购物
《燕子》教学反思
2014/02/18 职场文书
防沙治沙典型材料
2014/05/07 职场文书
2015元旦晚会主持词(开场白+结束语)
2014/12/14 职场文书
植树节新闻稿
2015/07/17 职场文书
django学习之ajax post传参的2种格式实例
2021/05/14 Python