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

2024-02-22

我的 HTML5 视频播放器有一个定制的搜索栏。但我需要突出显示搜索栏的一些预定义部分,例如秒2-5 and 7-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" alt="" 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>

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

然后您只需在画布上绘制标记即可。

只需对 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" alt="" 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>

Edit:

添加了 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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 HTML5 视频中突出显示播放器搜索栏 的相关文章

  • 如何转义 HTML 字符?在.NET中-->“

    如何在 NET 中转义 HTML 字符 我正在从 json 字符串中获取 html 并在标题中得到 amp quot more text 看起来我需要做两次才能得到 amp quot 成为 quot 那么它就是一个 如何转义 NET 中的所
  • 为什么这行带有“await”的代码会触发微任务队列处理?

    以下引用是我理解微任务队列处理的主要参考 当 JS 堆栈清空时 就会处理微任务 承诺使用 杰克 阿奇博尔德 https twitter com jaffathecake status 954653170986311680 这对我来说没有意义
  • 将按钮文本放在一行上

    我的按钮文本在 safari 中显示在一行上 即使在初次单击后 但是在 google chrome 上 当您第一次到达该按 钮时 我的按钮将显示在一行上 但是当您浏览更多帖子并再次遇到 加载更多 按钮时 文本搞砸了 这只发生在谷歌浏览器上
  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 检索 css3 缩放元素的宽度/高度

    我正在与 offsetWidth 属性的奇怪之处 我认为 作斗争 这是场景 比方说 我有一个span标签 在我的js中 在某个时刻我执行css3转换 对于这个元素 例如 el set styles transform scale scale
  • 使用 CSS 网格布局使网格项内的元素高度相等

    我在长度超过 4 的 div 中有一系列文章 没有任何舍入行标签 我需要将其表示为每行 3 篇文章 列 的表格 可能包含display grid 每篇文章都有页眉 章节和页脚 如何在每行文章内实现每个标题的等高 每个部分的等高以及与文章底部
  • 全局传递 xhr onload 函数的值

    在我正在创建的应用程序中 我有以下 XMLHttpRequest 并且我正在尝试传递结果data在 的里面xhr onload 到在同一父函数中创建的数组中 var url http api soundcloud com resolve j
  • 如何在 Web 服务器上设置 gzip 压缩?

    我有一个嵌入式网络服务器 总共有 2 兆空间 通常 您使用 gzip 文件对客户端有利 但这会节省我们在服务器上的空间 我读到你可以只 gzip js 文件并将其保存在服务器上 我在 IIS 上测试过 但没有任何运气 为了使这项工作成功 我
  • 使用 JQuery 禁用和启用所有超链接

    我有以下禁用所有超链接的内容 但在事件发生后我想再次启用它们 我该如何执行此操作 a click function return false 我认为这不仅仅是将其设置为 true 那么简单 谢谢大家 不要以这种方式绑定 点击 处理程序 而是
  • 如果一个对象结构与另一个对象结构不匹配/不匹配,如何引发异常

    我将读取格式正确的用户输入对象 也就是说 输入对象现在可以具有接口中未定义的任何键或子结构 如果用户提供了无效的对象 我如何抛出异常 预定义接口 export interface InputStructureInterface tableN
  • 如何通过 jQuery 中的类获取特定 html 元素的innerHTML?

    我有这样的 HTML 代码 div class a html value 1 div div class a html value 2 div 我怎样才能访问html value 1 and html value 2使用jquery 分别地
  • 如何使用新的analytics.js跟踪多个帐户?

    我需要使用 Google 的新的analytics js 跟踪一个页面上两个帐户的综合浏览量 有大量教程和示例如何使用较旧的 ga js 进行操作 但我发现的只是这个分析文档页面 https developers google com an
  • 如何在 webpack 中渲染嵌套的 SASS?

    采取以下CSS MyComponent color blue Button color red 以及以下 React 组件 import React from react import classes from MyComponent sc
  • Javascript 浮点乘以 100 仍然有错误

    我有一个货币字段的文本输入 我在字段中输入 33 91 并在尝试使用 乘以 100 技术时得到以下结果 var curWth parseInt trans withdraw index val 100 3390 var curWth par
  • 如何重复 ajax 请求,直到满足 RxJS Observable 的条件?

    我正在尝试重复请求 直到响应包含使用 RxJS 的数据 此时我想调用成功 或失败 处理程序 但我在使用 RxJS 时遇到了麻烦 这是我目前的方法 redux observable action observable mergeMap gt
  • 如何垂直对齐div内的图像

    如何在包含的内容中对齐图像div Example 在我的示例中 我需要将 img in the div with class frame div class frame style height 25px img src http jsfi
  • Bootstrap 导航栏与 Google 位置重叠自动完成下拉菜单

    我有一个导航栏 我试图在其中添加一个地点搜索框 除了谷歌位置提示框的一小部分被导航栏重叠 如下图所示 之外 一切几乎都有效 我尝试过改变z index输入框的值改为10或2000或90000但似乎没有效果 我还缺少其他需要做的事情吗 这是
  • d3.event.translate 在触摸设备的缩放上包含 NaN

    我使用 d3 为我的 svg 编写了一个自定义缩放函数 如下所示 Zoom behavior function myzoom xpos d3 event translate 0 ypos d3 event translate 1 vis a
  • 如何映射轮播的子项数组?

    我正在尝试将 Carousel 组件包装在映射对象数组周围作为组件的子级 目前我只能让映射创建映射对象的 1 个子对象 轮播需要像这样
  • 如何在 Jquery/Javascript 中绑定模糊和更改,但只触发一次函数?

    我试图在选择元素更改时触发函数 由于 Ipad 在 on change 方面遇到问题 我还想绑定到 blur 这在 Ipad 上工作得很好 但是我不希望两个事件都触发该函数两次 所以我需要某种挂钩来确保两个事件是否都触发change and

随机推荐

  • 我想从 servlet 添加一些纯文本内容和两个标头到 HttpServletResponse

    我想添加一些纯文本和两个标题到HttpServletResponse 代码如下 resp setContentType text plain resp getWriter write messages get next getContent
  • 在 Electron 应用程序中作为子进程运行时,Python 将找不到已安装的模块

    我在尝试使用 Electron 中运行 python 脚本时遇到了一些麻烦子进程模块 我最近在我的计算机 OSX 10 11 2 上安装了 Anaconda 并创建了以下脚本 import pandas as pd from pandasq
  • 从矩阵计算元素平均值

    我有一组存储在文本文件中的矩阵 我想计算输入矩阵的元素平均值所产生的输出矩阵 如下图所示 cat file1 txt Item0 Item1 Item0 1 01456e 06 5 Item1 2 12 2 cat file2 txt It
  • 我是否应该垂直翻转使用 stb_image 加载的图像的线条以在 OpenGL 中使用?

    我正在开发一个基于 OpenGL 的 2d 引擎 我使用 stb image 加载图像数据 以便创建 OpenGL 纹理 我知道 OpenGL 的 UV 原点是左下角 我也打算在该空间中处理我的屏幕空间 2d 顶点 即我正在使用 glm o
  • 在 C# 中加密文件并在 flutter 中解密

    我已经使用 C 代码加密了一个文件RijndaelManaged可以在System Security Cryptography 该文件需要传输到使用 dart flutter 开发的移动应用程序 我需要使用 dart 代码对其进行解密并将其
  • 如何获取仍在加载的声音对象的最终长度?

    我正在 ActionScript 3 中创建一个基本的 MP3 播放器 我有一个基本的进度条 指示歌曲已播放了多少 进度以 0 到 1 之间归一化的小数百分比计算 如下所示 var progress Number channel posit
  • 获取一段时间内每个季节的最大降雨量值 (xarray)

    我正在尝试找到每个季节的最大降雨量值 DJF MAM JJA SON 超过10年的时间 我正在使用 netcdf data 和 xarray 来尝试执行此操作 数据包括降雨量 每 3 小时记录一次 纬度和经度数据 现在我有以下代码 ds g
  • Heroku 的 Djangocollectstatic 每次都会推送到 S3

    我将 django storages 用于 S3 和 S3BotoStorage 的静态文件 当我从本地计算机收集静态时 行为符合预期 仅修改后的文件被推送到 S3 此过程需要 python dateutils 1 5 来检查修改时间 然而
  • Chromecast 是否支持 MPEG-DASH 清单中的 TS 容器格式

    在他们的开发者文档中 他们表示支持以下内容 容器 MP4 CENC WebM MPEG DASH SmoothStreaming 然而 MPEG DASH 和 SmoothStreaming 是允许各种容器的流协议 MPEG DASH 规范
  • 尝试识别 tomcat 中废弃连接的来源

    我在 tomcat 版本 7 中使用 dbcp 连接池 并且我的代码中某处存在连接泄漏 一小段时间后 新连接的请求将返回以下异常 无法获取连接 池错误等待空闲对象超时 我回顾了我的代码 对我来说 看起来所有连接都已正确关闭 不是每个人都这么
  • vuetify:以编程方式显示对话框

    vuetify 说 如果您想以编程方式打开或关闭对话框 可以通过使用带有布尔值的 v model 来实现 但是我很不清楚这意味着什么 说 使用 v model 充其量是模糊的 父组件在设置时知道它是否应该打开 但我不清楚如何在子组件中动态更
  • 为什么函数和类中处理未绑定局部变量的差异?

    当引用全局变量时 我们可以看到函数和类对此的处理方式不同 第一个很好 第二个会导致错误 x 10 class Foo x x 1 a foo Vs x 10 def faa x x 1 faa In the Python执行模型 https
  • Java TCP 在同一套接字上的客户端和服务器端之间发送和接收多个消息

    我有以下情况 TCP服务器将接受来自客户端的连接 客户端将发送第一个请求 服务器将响应该请求 并且服务器必须在同一套接字上等待以接收来自同一客户端的下一个请求 请参阅我所做的代码 使用此代码 服务器无法接收服务器发送的第二个请求 并且客户端
  • 修改 IQueryable.Include() 的表达式树以向连接添加条件

    基本上 我想实现一个存储库 即使通过导航属性也可以过滤所有软删除记录 所以我有一个基本实体 类似这样 public abstract class Entity public int Id get set public bool IsDele
  • webapp2 与 python3

    我使用带有或不带 googleAppEngine 的 webapp2 和 python 2 7 我现在尝试将它与 Python 3 3 一起使用 我已经使用 PIP 安装 webapp2 安装运行成功 但是当我尝试从 IDLE 导入 web
  • 文件系统观察器双条目

    我制作了一个小型 winforms 应用程序来监视某个文件夹中是否有新的 pdf 文件 如果在特定文件夹中创建了新的 pdf 文件 它会将其复制到其他位置 我遇到的问题是文件系统观察程序在我的列表框中创建了两个 多个条目 我该如何解决这个问
  • 当按下 Enter 键时,如何根据具有焦点的文本框触发按钮单击事件?

    我有一个带有几个提交按钮的表单 我希望根据当前具有焦点的文本框按下 Enter 键时触发按钮的单击事件 我可以使用下面的代码指定一个按钮 方法是将 onkeydown 事件添加到页面正文并检查 Enter 的 keyCode 我假设可以修改
  • 为什么应该重用 XmlHttpRequest 对象?

    据我了解 尽可能重用 XmlHttpRequest 对象是最佳实践 不幸的是 我很难理解为什么 看来 通过尝试重用 XHR 对象 您会增加代码复杂性 并引入可能的浏览器不兼容 http keelypavan blogspot com 200
  • WPF 列表框 SelectionChanged 事件

    我的列表框有问题 当我在程序中单击一个 ListBoxItem 时 我想更改 打开窗口并在之前对其进行预排序 但问题是它首先触发事件 然后更改选择 代码 private void LB Playlist SelectionChanged o
  • 在 HTML5 视频中突出显示播放器搜索栏

    我的 HTML5 视频播放器有一个定制的搜索栏 但我需要突出显示搜索栏的一些预定义部分 例如秒2 5 and 7 8 我怎样才能做到这一点 基本上 我需要它是这样的 到目前为止 这是我的简单代码