简单的 js 滑块,读取 ofssetX 使处理程序跳动
simple js slider, read of ofssetX make handler jumpy
我正在尝试使用纯 javascript 构建非常简单的水平滑块,我不想要任何像 jquery 这样的库。任务一开始似乎很容易,但我遇到了一个问题。我正在尝试从 offsetX
属性 获取读数以将处理程序设置在正确的位置。问题是,当我在轨道上滑动处理程序时,它有时会切换事件目标并将读数从处理程序更改为跟踪到滑块容器。这整个过程视觉效果不是最好的。
我是这样构造的:
<div class="slider">
<div class="track">
<div class="handler"></div>
</div>
</div>
以及后面的代码:
var dragging = false;
document.querySelector('.slider').onmousemove = function(event) {
if(dragging) {
document.querySelector('.handler').style.left = (event.offsetX - 15) + 'px';
}
};
document.querySelector('.handler').onmousedown = function(event) {
dragging = true;
};
window.onmouseup = function(event) {
dragging = false;
}
我认为解决方案是防止错误读数(来自处理程序或轨道)的事件,并且始终只使用鼠标相对于滑块的位置 div。但是我还不知道该怎么做。有没有人? ;)
您的假设是正确的,因为 event.offsetX
是相对于原始事件目标的,您从处理程序、轨道和滑块获得不同的值。您可以根据相对于客户端 window 的滑块和鼠标位置来计算偏移量。查看附加的代码片段。
var dragging = false;
var sliderEl = document.querySelector('.slider');
var handlerEl = document.querySelector('.handler');
sliderEl.onmousemove = function(event) {
if (dragging) {
var sliderRect = sliderEl.getBoundingClientRect();
var offset = Math.max(event.clientX - sliderRect.left, 0);
offset = Math.min(offset, sliderRect.width);
handlerEl.style.left = (offset - 15) + 'px';
}
return false;
};
handlerEl.onmousedown = function(event) {
dragging = true;
};
window.onmouseup = function(event) {
dragging = false;
}
#container {
width: 500px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.slider,
.slider * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.slider {
background: #ccc;
border: solid 1px #000;
width: 100%;
height: 100%;
position: relative;
}
.slider .track {
width: 100%;
background: #000;
height: 20px;
position: absolute;
top: calc(50% - 10px);
}
.slider .track .handler {
border: solid 1px #fff;
width: 30px;
height: 30px;
background: lime;
position: absolute;
top: calc(50% - 15px);
left: 0px;
cursor: pointer;
}
<div id="container">
<div class="slider">
<div class="track">
<div class="handler"></div>
</div>
</div>
</div>
我正在尝试使用纯 javascript 构建非常简单的水平滑块,我不想要任何像 jquery 这样的库。任务一开始似乎很容易,但我遇到了一个问题。我正在尝试从 offsetX
属性 获取读数以将处理程序设置在正确的位置。问题是,当我在轨道上滑动处理程序时,它有时会切换事件目标并将读数从处理程序更改为跟踪到滑块容器。这整个过程视觉效果不是最好的。
我是这样构造的:
<div class="slider">
<div class="track">
<div class="handler"></div>
</div>
</div>
以及后面的代码:
var dragging = false;
document.querySelector('.slider').onmousemove = function(event) {
if(dragging) {
document.querySelector('.handler').style.left = (event.offsetX - 15) + 'px';
}
};
document.querySelector('.handler').onmousedown = function(event) {
dragging = true;
};
window.onmouseup = function(event) {
dragging = false;
}
我认为解决方案是防止错误读数(来自处理程序或轨道)的事件,并且始终只使用鼠标相对于滑块的位置 div。但是我还不知道该怎么做。有没有人? ;)
您的假设是正确的,因为 event.offsetX
是相对于原始事件目标的,您从处理程序、轨道和滑块获得不同的值。您可以根据相对于客户端 window 的滑块和鼠标位置来计算偏移量。查看附加的代码片段。
var dragging = false;
var sliderEl = document.querySelector('.slider');
var handlerEl = document.querySelector('.handler');
sliderEl.onmousemove = function(event) {
if (dragging) {
var sliderRect = sliderEl.getBoundingClientRect();
var offset = Math.max(event.clientX - sliderRect.left, 0);
offset = Math.min(offset, sliderRect.width);
handlerEl.style.left = (offset - 15) + 'px';
}
return false;
};
handlerEl.onmousedown = function(event) {
dragging = true;
};
window.onmouseup = function(event) {
dragging = false;
}
#container {
width: 500px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.slider,
.slider * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.slider {
background: #ccc;
border: solid 1px #000;
width: 100%;
height: 100%;
position: relative;
}
.slider .track {
width: 100%;
background: #000;
height: 20px;
position: absolute;
top: calc(50% - 10px);
}
.slider .track .handler {
border: solid 1px #fff;
width: 30px;
height: 30px;
background: lime;
position: absolute;
top: calc(50% - 15px);
left: 0px;
cursor: pointer;
}
<div id="container">
<div class="slider">
<div class="track">
<div class="handler"></div>
</div>
</div>
</div>