自定义range sliders滑块实现元素拖动方法

 更新时间:2022年08月17日 10:20:14   作者:西炒蛋  
这篇文章主要为大家介绍了自定义range sliders滑块实现元素拖动方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1. 使用原生 range input

这篇文章介绍两种创建 range slider 滑块的方法。

老样子,话不多说,先上菜。

const knob = document.getElementById('knob');
// 左边的滑条
const leftSide = knob.previousElementSibling;
// 当前鼠标位置
let x = 0;
let y = 0;
let leftWidth = 0;
// 处理 mousedown 事件
const mouseDownHandler = function (e) {
  // 获取当前鼠标位置
  x = e.clientX;
  y = e.clientY;
  leftWidth = leftSide.getBoundingClientRect().width;
  // 在 `document` 上添加事件
  document.addEventListener('mousemove', mouseMoveHandler);
  document.addEventListener('mouseup', mouseUpHandler);
};
knob.addEventListener('mousedown', mouseDownHandler);
const mouseMoveHandler = function (e) {
  // 鼠标移动的距离
  const dx = e.clientX - x;
  const dy = e.clientY - y;
  const containerWidth = knob.parentNode.getBoundingClientRect().width;
  let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
  // 限制范围在 0 - 100
  newLeftWidth = Math.max(newLeftWidth, 0);
  newLeftWidth = Math.min(newLeftWidth, 100);
  leftSide.style.width = `${newLeftWidth}%`;
};
// 当松开鼠标时触发
const mouseUpHandler = function () {
  // ...
  // 移除事件
  document.removeEventListener('mousemove', mouseMoveHandler);
  document.removeEventListener('mouseup', mouseUpHandler);
};

input 元素本身支持设置 type 属性为 range,渲染一个 slider 滑块。

<input type="range" />

它的兼容性也还不错,支持所有现代浏览器以及 IE10 以上,但是它也有一些限制,比如:

  • 你不能自定义把手(中间蓝色圆圈)
  • 并不是所有现代浏览器都支持垂直方向的 slider 滑块

也就是说,它的自定义性不是很好,如果想要自定义 slider 滑块的话,这种方式就无法满足。

另外,兼容性方面我们可以通过下面这段代码来进行检测:

const isRangeInputSupported = function () {
  const ele = document.createElement('input');
  ele.setAttribute('type', 'range');
  // 如果当前浏览器不支持 `range` input
  // `type` 属性会还原到 `text`
  return ele.type !== 'text';
};

利用浏览器本身的默认行为机制,来判断当前浏览器是否支持 range input。

2. 创建自定义 range slider

一个 slider 滑块由 3 部分组成,1 个把手和把手左右两个的 2 个滑条。

我们先构造 HTML 结构,代码如下:

<div class="container">
  <div class="left"></div>
  <div class="knob" id="knob"></div>
  <div class="right"></div>
</div>

这 3 部分元素放置在同一行展示,右边部分的滑条表示的的是 range input 的可用宽度。所以,我们可以使用如下 CSS 代码进行布局。

.container {
  /* 内容水平居中 */
  display: flex;
  align-items: center;
  height: 1.5rem;
}
.right {
  /* 可用宽度 */
  flex: 1;
  height: 2px;
}

HTML 和 CSS 结构有了,我们接着来处理拖动行为。

监听 knob 把手的 mousedown 事件,记录当前鼠标的位置。

const knob = document.getElementById('knob');
// 左边的滑条
const leftSide = knob.previousElementSibling;
// 当前鼠标位置
let x = 0;
let y = 0;
let leftWidth = 0;
// 处理 mousedown 事件
const mouseDownHandler = function (e) {
  // 获取当前鼠标位置
  x = e.clientX;
  y = e.clientY;
  leftWidth = leftSide.getBoundingClientRect().width;
  // 在 `document` 上添加事件
  document.addEventListener('mousemove', mouseMoveHandler);
  document.addEventListener('mouseup', mouseUpHandler);
};
knob.addEventListener('mousedown', mouseDownHandler);

上面的代码要注意,mousedown 事件监听在 knob 元素上,而 mousemovemouseup 事件则是监听在 document 元素上。

document 元素上的监听回调事件 mouseMoveHandlermouseUpHandler 请看下文。

计算左侧滑条宽度

当 knob 把手移动时,通过当前鼠标位置和记录的鼠标位置,我们可以知道鼠标移动的距离,这段距离就是左侧滑条的宽度。

const mouseMoveHandler = function (e) {
  // 鼠标移动的距离
  const dx = e.clientX - x;
  const dy = e.clientY - y;
  const containerWidth = knob.parentNode.getBoundingClientRect().width;
  let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
  // 限制范围在 0 - 100
  newLeftWidth = Math.max(newLeftWidth, 0);
  newLeftWidth = Math.min(newLeftWidth, 100);
  leftSide.style.width = `${newLeftWidth}%`;
};

移除 document 元素上的监听事件

当滑动行为结束,也就是松开鼠标的时候,我们还需要移除掉 document 元素上的监听事件,防止重复监听导致的问题。

// 当松开鼠标时触发
const mouseUpHandler = function () {
  // ...
  // 移除事件
  document.removeEventListener('mousemove', mouseMoveHandler);
  document.removeEventListener('mouseup', mouseUpHandler);
};
<div style="display: flex; justify-content: center; padding: 4rem">
  <div style="width: 16rem" class="container">
    <div class="left"></div>
    <div class="knob" id="knob"></div>
    <div class="right"></div>
  </div>
</div>

以上就是自定义range sliders滑块实现元素拖动方法的详细内容,更多关于range sliders滑块元素拖动的资料请关注脚本之家其它相关文章!

相关文章

  • TypeScript基础类型介绍

    TypeScript基础类型介绍

    这篇文章主要介绍了TypeScript基础类型,布尔值、数字、字符串、任意类型等多种类型,下面我们就来看看这些类型的详细介绍,需要的朋友可以参考一下,希望对你有所帮助
    2021-12-12
  • 一文了解什么是TypeScript?

    一文了解什么是TypeScript?

    这篇文章主要介绍了什么是TypeScript,TypeScript是JavaScript的超集,它可以编译成纯JavaScript代码,TypeScript可以运行在浏览器环境、Node.js环境或者ECMAScript3或者更高的JavaScript的引擎中,下面我们就进入文章一起学习TypeScript的详细内容吧
    2021-12-12
  • 业务层hooks封装useSessionStorage实例详解

    业务层hooks封装useSessionStorage实例详解

    这篇文章主要为大家介绍了业务层hooks封装useSessionStorage实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Openlayer add mark及添加hover效果实例详解

    Openlayer add mark及添加hover效果实例详解

    这篇文章主要为大家介绍了Openlayer add mark及添加hover效果实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 前端JavaScript多数元素的算法详解

    前端JavaScript多数元素的算法详解

    这篇文章主要介绍了前端JavaScript多数元素的算法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 微信小程序 实现tabs选项卡效果实例代码

    微信小程序 实现tabs选项卡效果实例代码

    这篇文章主要介绍了微信小程序 实现tabs选项卡效果实例代码的相关资料,需要的朋友可以参考下
    2016-10-10
  • 如何利用javascript做简单的算法

    如何利用javascript做简单的算法

    这篇文章主要介绍了如何利用javascript做简单的算法,主要是以提问的形式犹如练习小例子然后解决问题并附代码说明,需要的朋友可以参考一下
    2021-11-11
  • 用Move.js配合创建CSS3动画的入门指引

    用Move.js配合创建CSS3动画的入门指引

    这篇文章主要介绍了用Move.js配合创建CSS3动画的入门指引,文中介绍了这个JavaScript库中的一些基本方法的使用,需要的朋友可以参考下
    2015-07-07
  • 前端算法leetcode109题解有序链表转换二叉搜索树

    前端算法leetcode109题解有序链表转换二叉搜索树

    这篇文章主要为大家介绍了前端算法leetcode109题解有序链表转换二叉搜索树示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 微信小程序 form组件详解及简单实例

    微信小程序 form组件详解及简单实例

    这篇文章主要介绍了微信小程序 form组件详解及简单实例的相关资料,需要的朋友可以参考下
    2017-01-01

最新评论