构建自定义音量滑块

时间:2019-04-02 13:08:16

标签: javascript

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

注释:由于该点击功能正常运行,我已将其注释掉。

正在发生的事情

  1. 如果您单击volumeBtn并在向左或向右滑动时不小心将光标移出了volumeRange div高度或宽度,则mouseup事件监听器不会当您停止单击鼠标时,将不会执行该操作。

  2. 就像1一样,单击volumeBtn后,一旦volumeBtn超出“ volumeRange” div范围,就无法向左或向右拖动。

  3. 从第零位置到所需位置存在闪烁。

我想发生的事情

  1. 如果单击volumeBtn然后停止单击鼠标,则即使光标不再位于mouseup上,也应执行volumeRange事件。

  2. 如果单击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>

1 个答案:

答案 0 :(得分:1)

为什么不起作用

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

对此的一种直接的(但不是很好)的解决方案是将“ 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>

其他问题

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