HTML5 视频播放器进度条准确的工具提示

HTML5 Video Player Progress Bar Accurate Tooltip

大多数视频播放器都允许您点击进度条跳转到视频中的特定点,通过使用鼠标在进度条上的位置来大致计算出用户将跳到视频中的哪个点如果此时单击进度条。

如果进度条最大值较小计算正确。

这是一个例子:

$("#range").on("click", function(event){
    var tooltip = Math.round((event.offsetX / event.target.clientWidth) * parseInt(event.target.getAttribute('max')));
    if (tooltip < 0) {
        tooltip = 0
    }else if (tooltip > 10) {
        tooltip = 10
    } 
    $(".calculated").text("Calculated Value: " + tooltip)
    $(".real").text("Real Value: " + $(this).val())
});
.main{
    position: relative;
    width: 100%;
    margin-top: 50px
}

/* Tooltip text */
.main .tooltip {
  width: 120px;
  background-color: #555;
  color: #fff;
  text-align: center;
  padding: 5px;
  border-radius: 6px;
}

input{
    width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
    <span class="tooltip calculated">5</span>
    <span class="tooltip real">20</span>
    <input type="range" min="0" max="10" value="20" id="range">
</div>

但是如果进度条的最大值很大计算会不准确

这是一个例子:

$("#range").on("click", function(event){
    var tooltip = Math.round((event.offsetX / event.target.clientWidth) * parseInt(event.target.getAttribute('max')));
    if (tooltip < 0) {
        tooltip = 0
    }else if (tooltip > 1000) {
        tooltip = 1000
    } 
    $(".calculated").text("Calculated Value: " + tooltip)
    $(".real").text("Real Value: " + $(this).val())
});
.main{
    position: relative;
    width: 100%;
    margin-top: 50px
}

/* Tooltip text */
.main .tooltip {
  width: 120px;
  background-color: #555;
  color: #fff;
  text-align: center;
  padding: 5px;
  border-radius: 6px;
}

input{
    width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
    <span class="tooltip calculated">20</span>
    <span class="tooltip real">20</span>
    <input type="range" min="0" max="1000" value="20" id="range">
</div>

有没有其他方法可以让计算更准确?我很高兴听到任何建议。

因为点的宽度。

上图中,输入的实际长度为(100% - 点的宽度)

虽然可以简单地通过排除点的长度来计算,但不建议这样做,因为根据屏幕宽度或浏览器类型可能会出现错误。

我的解决方案是使用百分比。

$("#range").on("click", function(event) {
    var inputVal = parseInt(event.target.value);
    var inputMaxVal = parseInt(event.target.getAttribute("max"));
    var inputPercentage = inputVal / inputMaxVal * 100;

    var tmpVideo = document.getElementById("yourVideo");
    var videoDur = tmpVideo.duration;
    var videoCur = tmpVideo.currentTime;
    var videoPercentage = videoCur / videoDur * 100;

    $(".calculated").text("Calculated Value: " + inputPercentage);
    $(".real").text("Real Value: " + videoPercentage);
});

现在比较 inputPercentage 和 videoPercentage。

p.s。我可能理解错了问题,因为我使用的是翻译器。

您尝试的计算出现这么多错误的原因很明显。

您正确地识别出在较短的滑块宽度上具有较大 maxValue 的不精确性。

计算错误是因为范围滑块结不是从左到右以线性方式分布的。因此,offsetX 除以滑块宽度的简单划分是……不完整的。

滑块的“拇指”有宽度。因此,为了能够在将拇指保持在滑块内的同时获得最小值和最大值,结的分布方式会逐渐补偿从极端(拇指宽度的 +/-50%)到中间的宽度(拇指宽度的 0%)。换句话说,中间确实是中间值...但是 exteme 结被“偏移”了拇指宽度的百分比。


对于您用来显示计算值与“真实”值的 span,我添加了一个跨度用于计算差异,一个用于误差百分比。因此,正如您在下面看到的,我实现了大约 0.10% 或更低的最大错误百分比……我真的怀疑是否有可能比这更好! ;)

因此,为了确保我的计算在这里是紧凑的,我使用了千万级的超大范围(笑!)...并尝试进行最准确的计算。总会有错误……但我们的想法是在整个滑块宽度上保持最小和“一致”。

因为关键是关于拇指的宽度,所以我添加了一些取自 css-tricks 的 CSS 只是为了确保那个宽度。删除该样式不会改变任何内容(至少在 Chrome 上是这样)。我没有找到一种方法来以编程方式检索滑块的拇指宽度。所以你的简单解决方案是定义它。

希望下面的计算是清楚的。

$("#range").on("click", function(event) {

  // Get the slider's params
  let maxValue = parseInt(event.target.getAttribute('max'))
  let sliderWidth = event.target.clientWidth

  // That is the key value causing offsets in calculations
  let thumbWidth = 16

  // I made a named function just to have the calculation logic apart from the rest.
  let thumbCorrection = getOffsetXcorrection(event.offsetX, sliderWidth, thumbWidth)

  // Using that "thumb correction" in the basic intuitive calculation anyone would expect
  let clickedKnotch = (event.offsetX-thumbCorrection) / sliderWidth
  
  
  // The demo outputs
  var calculatedValue = Math.round(clickedKnotch * maxValue)
  let realValue = $(this).val()
  let difference = calculatedValue - realValue
  let errorPercentage = Math.abs((difference / maxValue) *100)

  $(".calculated").text("Calculated: " + calculatedValue)
  $(".real").text("Real: " + realValue)
  $(".difference").text("Diff: " + difference)
  $(".percentage").text("Error: " + errorPercentage.toFixed(2) + "%")
});


function getOffsetXcorrection(clickedPosition, fullWidth, thumbWidth) {
  
  // The middle is the 0% correction point
  let middle = fullWidth/2
  
  // The "error" always is about half the thumb width
  let halfThumbWidth = thumbWidth/2
  
  // So where occured the click in that context?
  let percentageFromMiddle = (middle - clickedPosition) / middle
  
  // Return the correction about the click position to use in a "linear" calculation
  let correction = percentageFromMiddle * halfThumbWidth
  return Math.round(correction)
}
.main {
  position: relative;
  width: 100%;
  margin-top: 50px
}


/* Tooltip text */

.main .tooltip {
  width: 120px;
  background-color: #555;
  color: #fff;
  text-align: center;
  padding: 5px;
  border-radius: 6px;
}

input {
  width: 100%;
  margin-top: 1em;
}

/* From CSS-tricks */
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  border: 0px solid #000000;
  height: 16px;
  width: 16px;
  border-radius: 3px;
  /*background: #ffffff;
  cursor: pointer;
  margin-top: -14px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; */
}

.main .percentage{
  background-color: tomato;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
  <span class="tooltip calculated">20</span>
  <span class="tooltip real">20</span>
  <span class="tooltip difference">0</span>
  <span class="tooltip percentage">0</span>
  <input type="range" min="0" max="10000000" value="20" id="range">
</div>