好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

  }

  }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/Charissa2017/article/details/104099156

查看更多关于原生js实现滑块区间组件的详细内容...

  阅读:50次