【问题标题】:Determine click position on progress bar?确定进度条上的点击位置?
【发布时间】:2015-02-04 00:54:28
【问题描述】:

是否可以使用纯 javascript 确定用户点击进度条的值/位置?

目前,我可以检测到元素的点击,但只能获取栏的当前位置,与用户的点击无关。

http://jsfiddle.net/bobbyrne01/r9pm5Lzw/

HTML

<progress id="progressBar" value="0.5" max="1"></progress>

JS

document.getElementById('progressBar').addEventListener('click', function () {
    alert('Current position: ' + document.getElementById('progressBar').position);
    alert('Current value: ' + document.getElementById('progressBar').value);
});

【问题讨论】:

    标签: javascript html progress


    【解决方案1】:

    您可以像这样获取您在元素内部单击的位置的坐标:

    只需从页面点击位置的坐标中减去元素的偏移位置即可。

    Updated Example

    document.getElementById('progressBar').addEventListener('click', function (e) {
        var x = e.pageX - this.offsetLeft, // or e.offsetX (less support, though)
            y = e.pageY - this.offsetTop,  // or e.offsetY
            clickedValue = x * this.max / this.offsetWidth;
    
        console.log(x, y);
    });
    

    如果要确定点击事件是否发生在值范围内,则必须将点击的值(相对于元素的宽度)与进度元素上设置的 value 属性进行比较:

    Example Here

    document.getElementById('progressBar').addEventListener('click', function (e) {
        var x = e.pageX - this.offsetLeft, // or e.offsetX (less support, though)
            y = e.pageY - this.offsetTop,  // or e.offsetY
            clickedValue = x * this.max / this.offsetWidth,
            isClicked = clickedValue <= this.value;
        
        if (isClicked) {
            alert('You clicked within the value range at: ' + clickedValue);
        }
    });
    <p>Click within the grey range</p>
    <progress id="progressBar" value="5" max="10"></progress>

    【讨论】:

    • 最好也考虑任何 scollbars 的位置(如果存在),所以:x = e.pageX - this.offsetLeft + document.body.scrollLeft; y = e.pageY - this.offsetTop + document.body.scrollTop;
    • @Octopus It doesn't seem like the scrollbar effects it.. 除非我错过了什么?
    • 你是对的。我很抱歉。我正在考虑不支持 pageX 的浏览器,因此您需要使用 clientX,例如:x = e.clientX - this.offsetLeft + document.body.scrollLeft; 这些天所有浏览器都完全支持 pageX 吗?
    • 我发现offsetLeft 返回进度元素与其父元素之间的距离,获取进度元素与整个视口之间的距离可能很有用,这可以通过progressElement.getBoundingClientRect().x
    【解决方案2】:

    $(document).ready(function() {
    
      $(".media-progress").on("click", function(e) {
    
        var max = $(this).width(); //Get width element
        var pos = e.pageX - $(this).offset().left; //Position cursor
        var dual = Math.round(pos / max * 100); // Round %
    
    
        if (dual > 100) {
          var dual = 100;
        }
    
    
        $(this).val(dual);
        $("#progress-value").text(dual);
    
      });
      
      
      });
    .media-progress {
      /*BG*/
      position: relative;
      width: 75%;
      display: inline-block;
      cursor: pointer;
      height: 14px;
      background: gray;
      border: none;
      vertical-align: middle;
    }
    
    .media-progress::-webkit-progress-bar {
      /*Chrome-Safari BG*/
      background: gray;
      border: none
    }
    
    .media-progress::-webkit-progress-value {
      /*Chrome-Safari value*/
      background: #17BAB3;
      border: none
    }
    
    .media-progress::-moz-progress-bar {
      /*Firefox value*/
      background: #17BAB3;
      border: none
    }
    
    .media-progress::-ms-fill {
      /*IE-MS value*/
      background: #17BAB3;
      border: none
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <progress value="5" max="100" class="media-progress"></progress>
    <div id="progress-value"></div>

    【讨论】:

    • 一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。
    【解决方案3】:

    如果您希望为通用 max 值(在本例中为 0 和 1 之间的值)单击该值,您只需要一些简单的数学运算。

    document.getElementById('progressBar').addEventListener('click', function (e) {
    
        var value_clicked = e.offsetX * this.max / this.offsetWidth;
        alert(value_clicked);
    
    });
    

    Fiddle

    【讨论】:

      【解决方案4】:

      我测试了你的项目,试试这个解决方案:

      document.getElementById('progressBar').addEventListener('click', function (e) {
          var x = e.pageX - this.offsetLeft;
          
          //Uncomment the following line to activate alert
          //alert('Current position: ' + document.getElementById('progressBar').position);
          
          //Save position before the click
          var startPos = document.getElementById('progressBar').position;
          
          //Convert x value to progress range [0 1]
          
          var xconvert = x/300; //cause width is 300px and you need a value in [0,1] range
          var finalx = (xconvert).toFixed(1); //round up to one digit after coma
          
          //Uncomment the following line to activate alert
          //alert('Click value: ' + finalx);
        
          //If you don't want change progress bar value after click comment the following line
          document.getElementById('progressBar').value = finalx;
          
          document.getElementById('result').innerHTML = ('Start position: ' + startPos + "<br/><br/>");
          document.getElementById('result').innerHTML += ('Current position: ' + document.getElementById('progressBar').position + "<br/>");
          document.getElementById('result').innerHTML += ('Current value: ' + document.getElementById('progressBar').value + "<br/></br/>");
          document.getElementById('result').innerHTML += ('Real click value: ' + xconvert + "<br/>");
          document.getElementById('result').innerHTML += ('Current value set in progressbar: ' + finalx + "<br/>");
      });
      #progressBar {
          width:300px;
      }
      <progress id="progressBar" value="0.5" max="1"></progress>
      <div id="result"></div>
      • 我将您的进度条宽度设置为 300 像素(您可以更改)
      • 在进度条中获取位置 x
      • 将 x 位置范围从 [0,300] 转换为 [0,1]
      • 更改进度条内的值

      输出:

      • 起始位置
      • 当前位置和值(点击后)
      • 实际点击值(未四舍五入)
      • 在进度条中设置的值(四舍五入)

      工作演示: http://jsfiddle.net/Yeti82/c0qfumbL

      感谢 bobbyrne01 更新更正!

      【讨论】:

      • jQuery 在这里并不真正需要,也不会出现在我的最终解决方案中,所以这是没有jQuery 的答案:jsfiddle.net/bobbyrne01/jomeh1vu
      • 感谢 bobbyrne01 的指正。在我的所有文档中添加 jQuery 是我的习惯:P 我不认为它可能是多余的。我更新了我的答案。
      【解决方案5】:

      投票最多的答案实际上并不能普遍适用。 这是因为您必须考虑所有 offsetParent 的所有 offsetLeft。 这是一个改进的答案。希望对你有帮助。

      __addProgressBarListener () {
            document.getElementById('video-player-progress-bar').addEventListener('click', function (e) {
              let totalOffset = this.offsetLeft
              let parent = this.offsetParent
              const maximumLoop = 10
              let counter = 0
              while (document.body !== parent && counter < maximumLoop) {
                counter += 1
                totalOffset += parent.offsetLeft
                parent = parent.offsetParent
              }
              const x = e.pageX - totalOffset // or e.offsetX (less support, though)
              const clickedValue = x / this.offsetWidth
              console.log('x: ', x)
              console.log('clickedValue: ', clickedValue)
            })
          },
      

      【讨论】:

      • 请尝试解释为什么其他投票不能普遍工作!这将有助于其他人更多地了解答案。
      【解决方案6】:

      我找到了一个使用纯 javascript 的简单解决方案。

      使用getBoundingClientRect()有所有属性来计算百分比。

      document.getElementById('progressBar').addEventListener('click', function (e) {
          var bounds = this.getBoundingClientRect();
          var max = bounds.width //Get width element
          var pos = e.pageX - bounds.left; //Position cursor
          var dual = Math.round(pos / max * 100); // Round %
      
          console.log('percentage:', dual);
      });
      

      【讨论】:

        【解决方案7】:

        click事件实际上接受了一个参数,该参数包含了包括点击位置信息在内的事件信息。您可以使用它来确定在进度条中发生点击的位置。

        document.getElementById('progressBar').addEventListener('click', function (event) {
        
            document.getElementById('result').innerHTML = ('Current position: ' + document.getElementById('progressBar').position + "<br/>");
                document.getElementById('result').innerHTML += ('Current value: ' + document.getElementById('progressBar').value + "<br/>");
                document.getElementById('result').innerHTML += ('Mouse click (absolute): ' + event.offsetX + ", " + event.offsetY + "<br/>");
        });
        <progress id="progressBar" value="0.5" max="1"></progress>
        <div id="result"></div>

        【讨论】:

        • 继续获取Mouse click (absolute): undefined, undefined
        【解决方案8】:

        对于那些愿意使用滑块而不是进度条的人来说,获取值会容易得多:

        HTML

        <input type="range" min="0" max="100" value="50" id="slider">
        

        JavaScript

        const slider = document.getElementById('slider');
        slider.onclick = () => alert('Current value: ' + slider.value);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-01
          • 2012-02-28
          相关资源
          最近更新 更多