LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

使用 HTML + JavaScript 实现范围选择滑块(附完整代码)

admin
2026年1月11日 10:28 本文热度 265
范围选择滑块组件为用户提供了直观的方式来进行数值范围的选择,相比于传统的输入框,它具有更好的用户体验和视觉反馈。特别适用于价格筛选、时间范围设置等场景。本文将介绍如何使用 HTML、CSS 和 JavaScript 实现一个可拖拽的范围选择滑块。

效果演示

这个范围选择滑块支持双滑块操作,用户可以通过拖动左侧滑块调整最小值,拖动右侧滑块调整最大值。同时支持点击轨道空白区域,滑块会自动跳转到最近的位置。滑块具有平滑的视觉反馈,拖动时会有放大效果,并显示当前选择的具体数值范围。

页面结构

页面主要包括滑块轨道和数值显示两个区域。滑块轨道显示滑块的整体轨迹和已选范围,数值显示显示当前选择的数值范围。
<div class="slider-container">  <div class="slider-track" id="sliderTrack"></div>  <div class="slider-range" id="sliderRange"></div>  <div class="slider-thumb" id="minThumb"></div>  <div class="slider-thumb" id="maxThumb"></div>  <div class="slider-labels">    <span id="minLabel">10</span>    <span id="maxLabel">100</span>  </div></div>
<div class="value-display">  当前选择区间:<span class="range-value" id="rangeValue">20 - 80</span></div>

核心功能实现

配置初始化

首先定义滑块的基础配置,包括最小值、最大值、当前选择值和步长。这些配置参数决定了滑块的行为特性。
const config = {  minValue10,  maxValue100,  currentMin20,  currentMax80,  step1};
let isDragging = null;

位置更新逻辑

updateSlider 函数负责根据当前数值计算滑块的位置,并更新视觉表现。它通过百分比计算滑块的 left 值,确保滑块位置与数值对应。
function updateSlider() {  const minPercent = ((config.currentMin - config.minValue) / (config.maxValue - config.minValue)) * 100;  const maxPercent = ((config.currentMax - config.minValue) / (config.maxValue - config.minValue)) * 100;
  minThumb.style.left = minPercent + '%';  maxThumb.style.left = maxPercent + '%';  sliderRange.style.left = minPercent + '%';  sliderRange.style.width = (maxPercent - minPercent) + '%';
  rangeValue.textContent = `${config.currentMin} - ${config.currentMax}`;  minLabel.textContent = config.minValue;  maxLabel.textContent = config.maxValue;}

拖拽事件处理

handleDrag 函数是拖拽的核心处理逻辑,它获取鼠标或触摸位置,转换为对应的数值,并根据当前拖拽的是最小值还是最大值滑块来更新配置。
function handleDrag(e) {  if (!isDragging) return;
  e.preventDefault();  const rect = sliderTrack.getBoundingClientRect();  const position = Math.max(0Math.min(rect.widthgetEventClientX(e) - rect.left));  const percentage = position / rect.width;  let value = Math.round(    (config.minValue + percentage * (config.maxValue - config.minValue) - config.minValue) / config.step  ) * config.step + config.minValue;
  value = Math.max(config.minValueMath.min(config.maxValue, value));
  if (isDragging === minThumb) {    config.currentMin = Math.min(value, config.currentMax);  } else {    config.currentMax = Math.max(value, config.currentMin);  }
  updateSlide();}

事件绑定机制

通过 addEventListener 方法为滑块添加鼠标和触摸事件监听,实现跨设备兼容。同时在全局注册移动和释放事件,确保拖拽过程的连续性。
minThumb.addEventListener('mousedown'function(e) {startDrag(e, minThumb);});minThumb.addEventListener('touchstart'function(e) {startDrag(e, minThumb);});maxThumb.addEventListener('mousedown'function(e) {startDrag(e, maxThumb);});maxThumb.addEventListener('touchstart'function(e) {startDrag(e, maxThumb);});sliderTrack.addEventListener('click', trackClick);document.addEventListener('mousemove', handleDrag);document.addEventListener('mouseup', endDrag);document.addEventListener('touchmove', handleDrag, { passivefalse });document.addEventListener('touchend', endDrag);

扩展建议

  • 添加键盘支持,让用户能用方向键微调数值

  • 支持自定义颜色主题,满足不同界面设计需求

  • 增加数值输入框,方便精确数值输入

完整代码

git地址:https://gitee.com/ironpro/hjdemo/blob/master/select-range/index.html
<!DOCTYPE html><html lang="zh-CN"><head>  <meta charset="utf-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>范围选择滑块</title>  <style>    * {margin0padding0box-sizing: border-box;}    body {background-color#f5f7fapadding30pxmin-height100vhdisplay: flex; flex-direction: column; align-items: center; color#444;}    .container {background: white; padding30pxwidth500pxmargin-bottom30pxbox-shadow0 2px 10px rgba(0000.08);}    h1 {text-align: center; color#333margin-bottom30pxfont-size22pxfont-weight500letter-spacing0.5px;}    .slider-container {position: relative; height50px;}    .slider-track {position: absolute; top50%transformtranslateY(-50%); width100%height4pxbackground#e0e0e0cursor: pointer;}    .slider-range {position: absolute; top50%transformtranslateY(-50%); height4pxbackground#2196F3;}    .slider-thumb {position: absolute; top50%transformtranslate(-50%, -50%); width20pxheight20pxbackground: white; border2px solid #2196F3border-radius50%cursor: grab; z-index10;}    .slider-thumb:hover {border-color#0d8aee;}    .slider-thumb.dragging {cursor: grabbing; transformtranslate(-50%, -50%scale(1.2); box-shadow0 0 0 4px rgba(331502430.2);}    .slider-labels {display: flex; justify-content: space-between; width100%color#777font-size14px;}    .value-display {text-align: center; margin-top20pxfont-size16pxcolor#555padding14pxbackground#f9f9f9border1px solid #eee;}    .range-value {font-size18pxfont-weight600color#2196F3margin0 5px;}  </style></head><body><div class="container">  <h1>范围选择滑块</h1>  <div class="slider-container">    <div class="slider-track" id="sliderTrack"></div>    <div class="slider-range" id="sliderRange"></div>    <div class="slider-thumb" id="minThumb"></div>    <div class="slider-thumb" id="maxThumb"></div>    <div class="slider-labels">      <span id="minLabel">10</span>      <span id="maxLabel">100</span>    </div>  </div>  <div class="value-display">    当前选择区间:<span class="range-value" id="rangeValue">20 - 80</span>  </div></div>
<script>  // 获取DOM元素  const sliderTrack = document.getElementById('sliderTrack');  const sliderRange = document.getElementById('sliderRange');  const minThumb = document.getElementById('minThumb');  const maxThumb = document.getElementById('maxThumb');  const minLabel = document.getElementById('minLabel');  const maxLabel = document.getElementById('maxLabel');  const rangeValue = document.getElementById('rangeValue');  // 滑块配置  const config = {    minValue10,    maxValue100,    currentMin20,    currentMax80,    step1  };
  let isDragging = null;  // 获取事件坐标  function getEventClientX(e) {    return e.type.includes('touch') ? e.touches[0].clientX : e.clientX;  }  // 更新滑块位置  function updateSlider() {    const minPercent = ((config.currentMin - config.minValue) / (config.maxValue - config.minValue)) * 100;    const maxPercent = ((config.currentMax - config.minValue) / (config.maxValue - config.minValue)) * 100;
    minThumb.style.left = minPercent + '%';    maxThumb.style.left = maxPercent + '%';    sliderRange.style.left = minPercent + '%';    sliderRange.style.width = (maxPercent - minPercent) + '%';
    rangeValue.textContent = `${config.currentMin} - ${config.currentMax}`;    minLabel.textContent = config.minValue;    maxLabel.textContent = config.maxValue;  }  // 处理拖拽  function handleDrag(e) {    if (!isDragging) return;    e.preventDefault();    const rect = sliderTrack.getBoundingClientRect();    const position = Math.max(0Math.min(rect.widthgetEventClientX(e) - rect.left));    const percentage = position / rect.width;    let value = Math.round((config.minValue + percentage * (config.maxValue - config.minValue) - config.minValue) / config.step) * config.step + config.minValue;
    value = Math.max(config.minValueMath.min(config.maxValue, value));
    if (isDragging === minThumb) {      config.currentMin = Math.min(value, config.currentMax);    } else {      config.currentMax = Math.max(value, config.currentMin);    }
    updateSlider();  }  // 开始拖拽  function startDrag(e, thumb) {    e.preventDefault();    isDragging = thumb;    thumb.classList.add('dragging');  }  // 结束拖拽  function endDrag() {    if (isDragging) {      isDragging.classList.remove('dragging');      isDragging = null;    }  }  // 轨道点击  function trackClick(e) {    if (isDragging) return;    const rect = sliderTrack.getBoundingClientRect();    const position = Math.max(0Math.min(rect.widthgetEventClientX(e) - rect.left));    const percentage = position / rect.width;    let value = Math.round((config.minValue + percentage * (config.maxValue - config.minValue) - config.minValue) / config.step) * config.step + config.minValue;
    value = Math.max(config.minValueMath.min(config.maxValue, value));
    const distToMin = Math.abs(value - config.currentMin);    const distToMax = Math.abs(value - config.currentMax);
    if (distToMin <= distToMax) {      config.currentMin = Math.min(value, config.currentMax);    } else {      config.currentMax = Math.max(value, config.currentMin);    }
    updateSlider();  }  // 绑定事件  minThumb.addEventListener('mousedown'function(e) {startDrag(e, minThumb);});  minThumb.addEventListener('touchstart'function(e) {startDrag(e, minThumb);});  maxThumb.addEventListener('mousedown'function(e) {startDrag(e, maxThumb);});  maxThumb.addEventListener('touchstart'function(e) {startDrag(e, maxThumb);});  sliderTrack.addEventListener('click', trackClick);  document.addEventListener('mousemove', handleDrag);  document.addEventListener('mouseup', endDrag);  document.addEventListener('touchmove', handleDrag, { passivefalse });  document.addEventListener('touchend', endDrag);  // 初始化  updateSlider();</script></body></html>


阅读原文:原文链接


该文章在 2026/1/12 10:53:05 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved