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 元素上,而 mousemove
和 mouseup
事件则是监听在 document 元素上。
document 元素上的监听回调事件 mouseMoveHandler
和 mouseUpHandler
请看下文。
当 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滑块元素拖动的资料请关注软件开发网其它相关文章!