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

Miette ·
更新时间:2024-11-13
· 1792 次阅读

目录

1. 使用原生 range input

2. 创建自定义 range slider

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

计算左侧滑条宽度

移除 document 元素上的监听事件

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滑块元素拖动的资料请关注软件开发网其它相关文章!



RANGE 方法

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章