Ползунок для Media Player
Есть ползунок который работает но проблема когда быстро перемещаешь в не поле он заходит за границы как это исправить ?
var slider = document.querySelector('.slider_point');
slider.onmousedown = function() {
pos3 = event.clientX;
document.onmousemove = function() {
pos1 = pos3 - event.clientX;
if ( (slider.offsetLeft <= 0 && pos1 >= 0) || (slider.offsetLeft+30 >= 500 && pos1 <= 0) ) {
return;
}
else {
pos3 = event.clientX;
slider.style.left = (slider.offsetLeft - pos1) + 'px';
}
}
document.onmouseup = function() {
document.onmouseup = null;
document.onmousemove = null;
}
}
.slider {
position: relative;
width: 500px;
height: 30px;
background: black
}
.slider_point {
position: absolute;
width: 30px;
height: 30px;
background: red;
}
<div class="slider">
<div class="slider_point"></div>
</div>
Ответы (3 шт):
Автор решения: Михаил Камахин
→ Ссылка
Как-то так
const sliderPoint = document.querySelector('.slider_point');
const slider = document.querySelector('.slider');
sliderPoint.addEventListener('mousedown', (e) => {
const shiftX = e.clientX - sliderPoint.getBoundingClientRect().left;
onMouseMove(e);
function moveAt(pageX) {
// console.log(pageX);
const sliderLeftMax = slider.getBoundingClientRect().left;
sliderPoint.style.transform = `translateX(${pageX - sliderLeftMax - shiftX}px)`;
}
function onMouseMove(event) {
const sliderRightMax = slider.getBoundingClientRect().right;
const sliderLeftMax = slider.getBoundingClientRect().left;
const sliderPointRightPos = sliderPoint.getBoundingClientRect().right;
const sliderPointLeftPos = sliderPoint.getBoundingClientRect().left;
const movementOutRight = (sliderPointRightPos - event.pageX - sliderPoint.offsetWidth + shiftX) < 0 ? true : false;
const movementOutLeft = (-sliderPointLeftPos + event.pageX - sliderPoint.offsetWidth - shiftX) < 0 ? true : false;
if (sliderPointRightPos >= sliderRightMax) {
sliderPoint.style.transform = `translateX(${slider.offsetWidth - sliderPoint.offsetWidth}px)`;
if (movementOutRight) {
// console.log('Движение в правой части на правом краю слайдера');
} else {
// console.log('Движение в левой части на правом краю слайдера');
moveAt(event.pageX);
}
return false;
}
if (sliderPointLeftPos <= sliderLeftMax) {
sliderPoint.style.transform = `translateX(${0}px)`;
if (movementOutLeft) {
// console.log('Движение в левой части на левом краю слайдера');
} else {
// console.log('Движение в правой части на левом краю слайдера');
moveAt(event.pageX);
}
return false;
}
// console.log(' ');
moveAt(event.pageX);
}
document.addEventListener('mousemove', onMouseMove);
removeMouseUp();
function removeMouseUp() {
document.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
document.onmouseup = null;
};
}
});
sliderPoint.ondragstart = function() {
return false;
};
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.slider {
position: relative;
width: 500px;
height: 30px;
background: black;
overflow: hidden;
}
.slider_point {
position: absolute;
width: 30px;
height: 100%;
background: red;
}
<div class="slider">
<div class="slider_point"></div>
</div>
Автор решения: Grundy
→ Ссылка
Это происходит из-за того, что обработчик события onmousemove выполняется с некоторой задержкой, поэтому при резком движении последнее запомненное положение может быть за контейнером.
Чтобы этого не происходило, необходимо проверять, что новая позиция не выходит за границу контейнера, а так же если она все же выходит, то не обновлять предыдущую позицию, чтобы не ломать расчет сдвига.
var slider = document.querySelector('.slider_point');
var sliderWidth = slider.offsetWidth;
var sliderMaxLeft = slider.parentNode.offsetWidth - sliderWidth;
var sliderMinLeft = 0;
slider.onmousedown = function(e) {
var prevPos = e.clientX;
document.onmousemove = function(e) {
var diff = e.clientX - prevPos; // вычисляем на сколько надо сместить слайдер
var pos = slider.offsetLeft + diff; // вычисляем новую позицию
if (pos < sliderMinLeft) { // если новая позиция меньше минимальной
pos = sliderMinLeft; // ставим минимальную
}
if (pos > sliderMaxLeft) { // если больше максимальной
pos = sliderMaxLeft; // ставим максимальную
}
slider.style.left = pos + 'px'; // устанавливаем элемент в рассчитанную позицию
if (e.clientX - slider.parentNode.offsetLeft > sliderMaxLeft + sliderWidth) {
// если мышка вышла за родительский элемент справа - ничего не делаем
return;
}
if (e.clientX - slider.parentNode.offsetLeft < sliderMinLeft) {
// если мышка вышла за родительский элемент слева - ничего не делаем
return;
}
// обновляем предыдущую позицию
prevPos = e.clientX;
}
document.onmouseup = function() {
document.onmouseup = null;
document.onmousemove = null;
}
}
* {
box-sizing: border-box;
}
.slider {
position: relative;
width: 500px;
height: 30px;
background: black
}
.slider_point {
position: absolute;
width: 30px;
height: 30px;
background: red;
}
<div class="slider">
<div class="slider_point"></div>
</div>
Автор решения: Stranger in the Q
→ Ссылка
Сложно у Вас очень, предлагаю оперировать состоянием в интервале 1 - 0, например при помощи css - переменных
document.querySelectorAll('knob').forEach(knob => {
knob.ondragstart = () => false;
const css = (prop) => getComputedStyle(knob).getPropertyValue(prop);
const s = parseFloat(css( '--w')) - parseFloat(css( '--k'));
let startValue, startX;
const move = (e) => {
let v = startValue + (e.clientX - startX) / s;
v = Math.max(0, Math.min(v, 1));
knob.style.setProperty('--val', v);
};
const up = () => {
removeEventListener('mouseup', up);
removeEventListener('mousemove', move);
};
knob.addEventListener('mousedown', (e) => {
startValue = +css('--val');
startX = e.clientX;
addEventListener('mousemove', move);
addEventListener('mouseup', up);
});
})
slider {
--w: 300px;
--k: 20px;
display: flex;
width: var(--w);
margin: 20px auto;
background: steelblue;
}
knob {
transition: 0.1s transform;
cursor: pointer;
padding: calc(0.5 * var(--k));
background: red;
margin-left: calc(calc(var(--w) - var(--k)) * var(--val));
}
knob:active {
transform: scale(1.5) rotate(90deg);
}
<slider><knob style="--val:0.5" /></slider>
<slider><knob style="--val:0.1" /></slider>
<slider><knob style="--val:0.0" /></slider>
<slider><knob style="--val:1.0" /></slider>