HTML5 视频播放器进度条准确提示
Posted
技术标签:
【中文标题】HTML5 视频播放器进度条准确提示【英文标题】:HTML5 Video Player Progress Bar Accurate Tooltip 【发布时间】:2021-05-26 22:14:38 【问题描述】:大多数视频播放器允许您单击进度条跳转到视频中的特定点,方法是使用鼠标在进度条上的位置来粗略计算出用户将跳到视频中的哪个点,如果此时点击进度条。
如果进度条最大值较小,则计算正确。
这是一个例子:
$("#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>
有没有其他解决方案可以得到更准确的计算?我很高兴听到任何建议。
【问题讨论】:
尝试将event.offsetX
记录到控制台,看看为什么计算结果不符合您的预期。听起来像一个 XY 问题。你想做什么?
是的,问题是像素数小于视频时长,所以计算不准确是正常的。 event.offsetX
没有错
【参考方案1】:
您尝试的计算中出现如此多错误的原因很明显。
您正确地识别出在较短的滑块宽度上带有较大的 maxValue
的不精确性。
计算错误来自于范围滑块结不是从左到右以线性方式分布的事实。因此,将offsetX
除以滑块的宽度是……不完整的。
滑块的“拇指”有一个宽度。因此,为了能够在将拇指保持在滑块内的同时获得最小值和最大值,结点的分布方式可以逐渐补偿从极端(拇指宽度的 +/-50%)到中间的宽度(拇指宽度的 0%)。换句话说,中间的值确实是中间值……但是外部结点“偏移”了拇指宽度的百分比。
在 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>
【讨论】:
如果您将拇指移动到滑块的开头或结尾,为什么错误会变得如此之大。 那是因为释放鼠标按钮时会发生click
事件。因此,在将拇指拖动到零时,如果在鼠标不在拇指上方时发生鼠标释放,则计算关闭。
也许你应该只使用input
事件的真实值...而不是click
。但我不知道你真正想用工具提示做什么。
即使点击不是真正的开始。错误发生在第一个假设范围滑块的 20px 处。问题不在于鼠标的释放。
只是 哇。即使是最著名的视频播放器也没有这个精确的计算方法!【参考方案2】:
因为点的宽度。
上图中,输入的实际长度为(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。
附言我可能误解了这个问题,因为我使用的是翻译器。
【讨论】:
以上是关于HTML5 视频播放器进度条准确提示的主要内容,如果未能解决你的问题,请参考以下文章