Ползунок для 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>

→ Ссылка