在 HTML5 视频中突出显示播放器搜索栏

Posted

技术标签:

【中文标题】在 HTML5 视频中突出显示播放器搜索栏【英文标题】:Highlight player seekbar in HTML5 video 【发布时间】:2020-06-29 02:43:27 【问题描述】:

我为我的 html5 视频播放器定制了一个搜索栏。但我需要突出显示搜索栏的一些预定义部分,例如秒 2-57-8。我该怎么做?

基本上,我需要它是这样的:

到目前为止,这是我的简单代码:

<!DOCTYPE html> 
<html> 
<head>

<style>
.body
background-color:black;

.video-player 
  position: relative;
  width: 66%;
  height: 66%;

.video-player img 
  width: 100%;
  height: 100%;

.video-player video 
  position: fixed;
  top: 0;
  left: 0;
  min-width: 66%;
  min-height: 66%;
  width: auto;
  height: auto;
  z-index: -100;
  background-repeat: no-repeat;

.video-player .controls 
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;

.video-player .controls .progress-bar 
  position: absolute;
  margin-left: 28%;
  bottom: 10%;
  color: orange;
  font-size: 12px;
  width: 40%;
  height: 8%;
  border: none;
  background: #434343;
  border-radius: 9px;
  vertical-align: middle;
  cursor: pointer;

.video-player .controls progress::-moz-progress-bar 
  color: orange;
  background: #434343;

.video-player .controls progress[value]::-webkit-progress-bar 
  background-color: #434343;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;

.video-player .controls progress[value]::-webkit-progress-value 
  background-color: orange;


video#backgroundvid 
  position: absolute;
  right: 0;
  bottom: 0;
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  z-index: -100;
  background-repeat: no-repeat;


</style>
</head>

<body>
<div class="video-player">
  <video preload="auto" autoplay loop id="backgroundvid">
    <source src="mov_bbb.mp4" type="video/mp4">
    Your browser does not support HTML5 video.
  </video>
  <img src="top2.png" style="object-fit:cover"  id="backgroundvid">
  <div class="controls">
    <progress class="progress-bar" style="object-fit:cover; z-index=10000" min="0" max="100" value="0">0% played</progress>
  </div>
</div>

<script>
const player = document.querySelector('.video-player');
const video = player.querySelector('video');
const progressBar = player.querySelector('.progress-bar');

video.addEventListener('timeupdate', updateProgressBar, false);
progressBar.addEventListener('click', seek);

function updateProgressBar() 
  var percentage = Math.floor((100 / video.duration) * video.currentTime);
  progressBar.value = percentage;
  progressBar.innerHTML = percentage + '% played';


function seek(e) 
  let percent = e.offsetX / this.offsetWidth;
  video.currentTime = percent * video.duration;
  e.target.value = Math.floor(percent / 100);
  e.target.innerHTML = progressBar.value + '% played';

</script>
</body> 
</html>

【问题讨论】:

【参考方案1】:

您可以使用将叠加在进度条顶部的画布,

然后您只需在此画布中绘制标记。

只需对 html 做些微改动(在进度条上添加一个 id id="progress-bar"):

<progress id="progress-bar" class="progress-bar" style="object-fit:cover; z-index=10000" min="0" max="100" value="0">0% played</progress>

添加 CSS 以设置画布的样式(与进度条相同的 CSS 属性)

#markers
    position: absolute;
    bottom: 10%;
    margin-left: 28%;
    border-radius: 9px;
    pointer-events: none;

注意pointer-events: none;,如果不放,就无法控制进度条。

因此,创建和插入画布的 javascript,然后在其上放置标记。

// We need the metadata 'duration', so we wrap the code in an event listener to be sure we execute our code when the metadata is loaded
video.addEventListener('loadedmetadata', function () 
    // Get the dimension of the progress-bar
    const progressbar = document.getElementById('progress-bar');
    const widthProgressBar = window.getComputedStyle(progressbar, null).getPropertyValue("width");
    const heightProgressBar = window.getComputedStyle(progressbar, null).getPropertyValue("height");
    // Create the canvas
    const canvas = document.createElement('canvas');
    const w = canvas.width = parseFloat(widthProgressBar);
    const h = canvas.height = parseFloat(heightProgressBar);
    canvas.id = 'markers';
    const progressBar = document.getElementById("progress-bar");
    // Insert the canvas in the DOM
    progressBar.parentNode.insertBefore(canvas, progressBar.nextSibling)
    // Define the context
    const ctx = canvas.getContext('2d');
    // Calcul how many px will represent 1s
    const videoDuration = video.duration;
    const ratioPxBySeconds = parseFloat(w) / videoDuration;
    // Define the markers
    const markers = 
        'marker1': [2, 5],
        'marker2': [7, 8]
    ;

    // Function to draw the markers
    function setMarkers(markers, ratioPxSec, height) 
        for (marker in markers) 
            let x = markers[marker][0] * ratioPxSec; // Start x position of the marker
            let y = 0; // Start y position of the marker
            let w = (markers[marker][1] - markers[marker][0]) * ratioPxSec; // Width of the marker
            let h = parseFloat(height); // Height of the marker
            ctx.fillStyle = "#7f3302"; // Set the color of the marker
            ctx.fillRect(x, y, w, h); // Draw a rectangle
        
    

    setMarkers(markers, ratioPxBySeconds, h); // Call the function
);

const player = document.querySelector('.video-player');
const video = player.querySelector('video');
const progressBar = player.querySelector('.progress-bar');

video.addEventListener('timeupdate', updateProgressBar, false);
progressBar.addEventListener('click', seek);

function updateProgressBar() 
  var percentage = Math.floor((100 / video.duration) * video.currentTime);
  progressBar.value = percentage;
  progressBar.innerHTML = percentage + '% played';


function seek(e) 
  let percent = e.offsetX / this.offsetWidth;
  video.currentTime = percent * video.duration;
  e.target.value = Math.floor(percent / 100);
  e.target.innerHTML = progressBar.value + '% played';


// We need the metadata 'duration', so we wrap the code in an event listener to be sure we execute our code when the metadata is loaded
video.addEventListener('loadedmetadata', function() 
  // Get the dimension of the progress-bar
  const progressbar = document.getElementById('progress-bar');
  const widthProgressBar = window.getComputedStyle(progressbar, null).getPropertyValue("width");
  const heightProgressBar = window.getComputedStyle(progressbar, null).getPropertyValue("height");
  // Create the canvas
  const canvas = document.createElement('canvas');
  const w = canvas.width = parseFloat(widthProgressBar);
  const h = canvas.height = parseFloat(heightProgressBar);
  canvas.id = 'markers';
  const progressBar = document.getElementById("progress-bar");
  // Insert the canvas in the DOM
  progressBar.parentNode.insertBefore(canvas, progressBar.nextSibling)
  // Define the context
  const ctx = canvas.getContext('2d');
  // Calcul how many px will represent 1s
  const videoDuration = video.duration;
  const ratioPxBySeconds = parseFloat(w) / videoDuration;
  // Define the markers
  const markers = 
    'marker1': [2, 5],
    'marker2': [7, 8]
  ;

  // Function to draw the markers
  function setMarkers(markers, ratioPxSec, height) 
    for (marker in markers) 
      let x = markers[marker][0] * ratioPxSec; // Start x position of the marker
      let y = 0; // Start y position of the marker
      let w = (markers[marker][1] - markers[marker][0]) * ratioPxSec; // Width of the marker
      let h = parseFloat(height); // Height of the marker
      ctx.fillStyle = "rgb(127, 51, 2, 0.9)"; // Set the color of the marker
      ctx.fillRect(x, y, w, h); // Draw a rectangle
    
  

  setMarkers(markers, ratioPxBySeconds, h); // Call the function
  
  // Calculate the new dimensions & redraw
  function resize()
    const progressBar = document.getElementById('progress-bar');
    const w = canvas.width = progressBar.clientWidth;
    const h = canvas.height = progressBar.clientHeight;
    const ratioPxBySeconds = parseFloat(w) / videoDuration;
    setMarkers(markers, ratioPxBySeconds, h);
  
  // On page resize, call the resize() function
  window.addEventListener("resize", resize, false);
  
);
body 
  background-color: black;


.video-player 
  position: relative;
  width: 66%;
  height: 66%;


.video-player img 
  width: 100%;
  height: 100%;


.video-player video 
  position: fixed;
  top: 0;
  left: 0;
  min-width: 66%;
  min-height: 66%;
  width: auto;
  height: auto;
  z-index: -100;
  background-repeat: no-repeat;


.video-player .controls 
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;


.video-player .controls .progress-bar 
  position: absolute;
  margin-left: 28%;
  bottom: 10%;
  color: orange;
  font-size: 12px;
  width: 40%;
  height: 8%;
  border: none;
  background: #434343;
  border-radius: 9px;
  vertical-align: middle;
  cursor: pointer;


#markers 
  position: absolute;
  bottom: 10%;
  margin-left: 28%;
  border-radius: 9px;
  pointer-events: none;


.video-player .controls progress::-moz-progress-bar 
  color: orange;
  background: #434343;


.video-player .controls progress[value]::-webkit-progress-bar 
  background-color: #434343;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;


.video-player .controls progress[value]::-webkit-progress-value 
  background-color: orange;


video#backgroundvid 
  position: absolute;
  right: 0;
  bottom: 0;
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  z-index: -100;
  background-repeat: no-repeat;
<div class="video-player">
  <video preload="auto" autoplay loop id="backgroundvid">
    <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
    Your browser does not support HTML5 video.
  </video>
  <img src="https://i.stack.imgur.com/gmK7P.png" style="object-fit:cover"  id="backgroundvid">
  <div class="controls">
    <progress id="progress-bar" class="progress-bar" style="object-fit:cover; z-index=10000" min="0" max="100" value="0">0% played</progress>
  </div>
</div>

编辑:

添加了 resize() 函数以在屏幕调整大小时更新标记

(通常,当您将视频全屏播放时会发生这种情况)

// Calculate the new dimensions & redraw
function resize()
  const progressBar = document.getElementById('progress-bar');
  const w = canvas.width = progressBar.clientWidth;
  const h = canvas.height = progressBar.clientHeight;
  const ratioPxBySeconds = parseFloat(w) / videoDuration;
  setMarkers(markers, ratioPxBySeconds, h);

// On page resize, call the resize() function
window.addEventListener("resize", resize, false);

【讨论】:

我更改了标记填充样式以允许透明度。不透明的矩形隐藏了进度。 谢谢。我得到的有点乱(高亮条有点高):i.stack.imgur.com/WuFbc.jpg 好的,它是 10%,我更改了它并修复了它。谢谢。

以上是关于在 HTML5 视频中突出显示播放器搜索栏的主要内容,如果未能解决你的问题,请参考以下文章

突出显示搜索词

Thymeleaf 布局中的 Bootstrap 导航栏突出显示

突出显示在 Android 设置应用程序的搜索结果中找到的菜单项

在标签栏中设置自定义图标以突出显示/未突出显示

Plotly R 突出显示问题:当我点击一个栏时,突出显示看起来错误

在 mouseup 文本选择 + HTML5/jQuery 上覆盖突出显示的文本