我找到了this并尝试对其进行修复,因为其背后的逻辑与我要实现的逻辑相似。我已经设法通过最少的编辑工作了。但它没有按预期工作。

注意:我已将点击功能注释掉,因为它可以正常工作。

怎么了


如果单击volumeBtn并在向左或向右滑动时不小心将光标移出了volumeRange div高度或宽度,则当您停止单击鼠标时,不会执行mouseup事件侦听器。
像1一样,单击volumeBtn后,一旦volumeBtn超出`volumeRange'div之外,就不能向左或向右拖动。
从第零位置到所需位置存在闪烁。


我想发生什么


如果单击volumeBtn然后停止单击鼠标,则即使光标不再位于mouseup上,也应执行volumeRange事件。
如果单击volumeBtn,则即使光标不再位于volumeBtn上,您也应该能够向左或向右拖动volumeRange




    const volume = document.querySelector('.volume');
    const volumeRange = document.querySelector('.volume-range');
    const volumeBtn = document.querySelector('.volume-button');

    // volumeRange.addEventListener("click", volumeClick    );
    //     function volumeClick(event) {
    //         let x = event.offsetX;
    //         volume.style.width = (Math.floor(x) + 10) + 'px';
    //     }



        let mouseIsDown = false;

        volumeBtn.addEventListener("mouseup", up);
        volumeBtn.addEventListener("mousedown", down);
        volumeRange.addEventListener("mousemove", volumeSlide);

        function down(){ mouseIsDown = true; }
        function up(){ mouseIsDown = false; }

        function volumeSlide(event) {
            if (mouseIsDown) {
                let x = event.offsetX;
                console.log(x);
                volume.style.width = Math.floor(x + 10) + 'px';
            }
        }

    body {
        background-color: #2a2a2a;
    }

    .volume-range {
        margin-top: 80px;
        height: 5px;
        width: 250px;
        background: #555;
        border-radius: 15px;

    }

    .volume-range>.volume {
        height: 5px;
        width: 50px;
        background: #2ecc71;
        border: none;
        border-radius: 10px;
        outline: none;
        position: relative;
    }

    .volume-range>.volume>.volume-button {
        width: 20px;
        height: 20px;
        border-radius: 20px;
        background: #FFF;
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        cursor: pointer;
        outline: none;
    }

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>Volume</title <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>

</style>

<body>
    <div class="volume-range">
        <div class="volume">
            <div class="volume-button"></div>
        </div>
    </div>
</body>

</html>

最佳答案

为什么它不起作用

这是按照您描述的方式进行的,因为仅当鼠标位于连接了侦听器的元素内部时,才会触发鼠标事件。

对此的一种直接(但不是很好)的解决方案是将“ mouseup”和“ mousemove”的侦听器从volumeBtn / volumeRange移到window对象。这不是很好,因为如果以后需要删除此元素,则还应该从window对象中删除侦听器。

更好的解决方案

最好将滑块封装在另一个元素内,这将给它提供一些填充,然后将事件侦听器放在该“容器”元素上。当您移出元素之外时,它仍然会停止移动,但是至少所有内容都是独立的。

以下代码段显示了该代码:



const volume = document.querySelector('.volume');
    const volumeRange = document.querySelector('.volume-range');
    const volumeContainer = document.querySelector('.volume-container');
    const volumeBtn = document.querySelector('.volume-button');

    // volumeRange.addEventListener("click", volumeClick    );
    //     function volumeClick(event) {
    //         let x = event.offsetX;
    //         volume.style.width = (Math.floor(x) + 10) + 'px';
    //     }



        let mouseIsDown = false;

        volumeContainer.addEventListener("mouseup", up);
        volumeBtn.addEventListener("mousedown", down);
        volumeContainer.addEventListener("mousemove", volumeSlide, true);

        function down(){ mouseIsDown = true; }
        function up(){ mouseIsDown = false; }

    		const volumeRangeWidth = volumeRange.getBoundingClientRect().width; // This will be the volume limit (100%)

        function volumeSlide(event) {
            if (mouseIsDown) {
                let x = event.offsetX;
                if (event.target.className == "volume-container") {
                	x = Math.floor(x);
                  if (x < 0) x = 0; // check if it's too low
                  if (x > volumeRangeWidth) x = volumeRangeWidth; // check if it's too high
                  volume.style.width = (x+10) + 'px';
                }

            }
        }

body {
        background-color: #2a2a2a;
    }

    .volume-container {
      padding: 40px 0px;
      margin: 0px 20px;
    }

    .volume-range {
        height: 5px;
        width: 250px;
        background: #555;
        border-radius: 15px;

    }

    .volume-range>.volume {
        height: 5px;
        width: 50px;
        background: #2ecc71;
        border: none;
        border-radius: 10px;
        outline: none;
        position: relative;
    }

    .volume-range>.volume>.volume-button {
        width: 20px;
        height: 20px;
        border-radius: 20px;
        background: #FFF;
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        cursor: pointer;
        outline: none;
    }

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>Volume</title>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>

</style>

<body>
    <div class="volume-container">
      <div class="volume-range">
          <div class="volume">
              <div class="volume-button"></div>
          </div>
      </div>
    </div>
</body>

</html>





其他问题

在小提琴中,还显示了如何避免体积超出容器。

08-06 21:05