【问题标题】:HTML5 video media fragments with Javascript带有 Javascript 的 HTML5 视频媒体片段
【发布时间】:2019-07-21 20:49:40
【问题描述】:

这里没有人回答我的问题,但也许这是一个简单的问题? 我是编码新手,我正在尝试找到一种导航视频的方法,例如播放前 10 秒然后停止,播放 30-40 秒然后停止,播放第二个 60-30 然后停止等,并有按钮为了它。我找到了一个教程,但按钮没有响应。我已经清理了一些代码(不要认为我删除了任何必要的内容)并将其粘贴在下面。 教程链接: https://www.sitepoint.com/html5-video-fragments-captions-dynamic-thumbnails/

HTML:

<head>

    <meta charset="UTF-8">
    <title>Untitled Document</title>

    <link href="style.css" rel="stylesheet" type="text/css">
    <script type="text/javascript" src="script.js"></script>

</head>

<body>

<section class="wrapper">

  <div>
    <video id="frag1" controls preload="metadata">

      <source src="assets/disney.mp4"  type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' data-original="assets/disney.mp4">

      <source src="assets/disney.mp4" type='video/webm;codecs="vp8, vorbis"' data-original="assets/disney.mp4">

    </video>
    <nav>
      <button data-start="0">Section One</button>
      <button data-start="6">Section Two</button>
      <button data-start="17">Section Three</button>
    </nav>
  </div>

</section>


</body>

</html>

CSS:

@charset "UTF-8";

#main { width: 85%; margin: 1em auto; }

section>div { margin: 0 1.5% 1.5% 0; padding: 1.5%; float: left; background-color: #efefef; }


video { width: 100%; min-height: 430px; }
button { cursor: pointer; }
nav>button { margin: 0.27em; }
nav>button:first-child { margin-left: 0; }
.wrapper { width: 520px; margin: auto; overflow: hidden; text-align: center; }

.p {
  text-align: center;
  padding-top: 120px;
}

Resources 1×0.5×0.25× Rerun

JAVASCRIPT:

function mediaFragOne() 
{
var video, sources, nav, buttons;

video = document.querySelector('video#frag1');
sources = video.getElementsByTagName('source');
nav = document.querySelector('video#frag1+nav');
buttons = nav.getElementsByTagName('button');

for(var i = buttons.length - 1; i >= 0; i--) 
{
    buttons[i].addEventListener('click', function() {
            for (var i = sources.length - 1; i >= 0; i--) {
                sources[i].setAttribute(
                    'src', (sources[i].getAttribute('data-original')
                    .concat('#t=' + this.getAttribute('data-start'))));
                    video.load();
                    video.play();
            };
        });
    }
}
mediaFragOne();

【问题讨论】:

    标签: javascript html video


    【解决方案1】:

    当您有多个要点击的标签时,请使用Event Delegation

    1. 找到所有目标标签(例如&lt;a&gt;)共有的祖先标签(例如&lt;nav&gt;)。将祖先标签注册到事件。现在只要祖先标签或其后代标签触发注册事件,绑定到祖先标签的回调函数就会触发。所以本质上这是一个事件监听器,用于无限数量的目标标签。

      document.querySelector(ancestor).addEventListener('click', callback);
      
    2. 总是让回调函数通过Event Object

      function callback(event) {...
      
    3. 通过引用Event.target 来确定作为事件来源的标签(单击按钮、更新视频时间等...)。

      const clicked = event.target
      
    4. 在回调函数中,它应该只适用于目标标签并排除所有其他标签。

      if (clicked.matches('a')) {...
      ...}
      return false;
      

    demo中评论的详细信息

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset='utf-8'>
      <style>
         :root {
          font: 400 2.5vw/1.2 Consolas
        }
        
        .vid {
          display: block;
          margin: 0 auto;
          width: 80vw;
        }
        
        .btns {
          display: flex;
          justify-content: center;
          width: 80vw;
          margin: 0 auto;
        }
        
        a {
          display: block;
          margin: 5px 8px;
          border: 1px solid #000;
          border-radius: 8px;
          text-decoration: none;
          text-align: center;
          padding: 3px 5px;
          width: 15vw;
        }
      </style>
    </head>
    
    <body>
      <video class='vid' src='https://storage04.dropshots.com/photos6000/photos/1381926/20170326/005610.mp4' controls></video>
      <nav class='btns'>
        <a href='#/' data-start='00' data-end='10'>00 - 10</a>
        <a href='#/' data-start='10' data-end='20'>10 - 20</a>
        <a href='#/' data-start='20' data-end='30'>20 - 30</a>
        <a href='#/' data-start='30' data-end='40'>30 - 40</a>
      </nav>
      <script>
        // Declare end
        let end;
        // Reference the parent tag of all buttons
        const btns = document.querySelector('.btns');
        // Reference the video
        const vid = document.querySelector('.vid');
    
        // Register the click event to nav.btns
        btns.addEventListener('click', frag);
    
        // Register the timeupdate event to video.vid
        vid.addEventListener('timeupdate', stop);
    
        // Pass Event Object
        function frag(event) {
          // Event.target always points to the clicked button, time-updated video, etc.
          const clicked = event.target;
    
          // if clicked tag is an <a>...
          if (clicked.matches('a')) {
            // Get the value of its data-start and convert it to a real number
            let start = Number(clicked.dataset.start);
            // Set end to the value of it data-end and convert it to a real number
            end = Number(clicked.dataset.end);
            // Set video current time to value of start
            vid.currentTime = start;
            // Play video
            vid.play();
          }
          // End function
          return false;
        }
    
        // Pass Event Object
        function stop(event) {
          // Reference the video
          const vid = event.target;
    
          // if it is a <video>...
          if (vid.matches('video')) {
            // and if that video time is currently at or past the value of end...
            if (vid.currentTime >= end) {
              // Pause video
              vid.pause();
            }
          }
          // End function
          return false;
        }
      </script>
    </body>
    
    </html>

    【讨论】:

    • 谢谢,我知道这很枯燥 ? 但它有时间段的可视化表示
    • 感谢您提供的详细解释以及额外的阅读帮助。不幸的是,它仍然对我不起作用。页面加载,但按钮没有响应。人们在这里发布的代码都没有响应我开始怀疑我是否没有问题?我只是想知道它到底是什么。我正在使用 python -m SimpleHTTPServer 通过终端在 Dreamweaver 和 chrome 中测试页面
    • 我只是想检查一下控制台,它给了我这个错误(我无法格式化它,因为每次我点击输入此评论时都会保存:script.js:6 Uncaught TypeError: Cannot read property 'getElementsByTagName' 在 script.js:27 处的 mediaFragOne (script.js:6) 处为 null
    • 根据上面的建议,我也将这个上传到了我的服务器,现在它在控制台中给了我一条不同的错误消息: Uncaught TypeError: Cannot read property 'addEventListener' of null at script.js:9
    • 嗨@epignosis567 尝试在空白页上使用我的代码,我将更新sn-p,使其成为一个完整的页面。答案是独立的,可以很容易地适应普通页面,但是在将其集成到具有预先存在的 HTML、CSS 和 JavaScript(尤其是 CSS 和更多的 JS)的页面中时必须小心。关于第一个错误,我的回答没有使用document.getElementsByTagName(**tagName**)。但如果我需要通过tagName 收集元素——我会使用document.querySelectorAll('**tagName**),因为前者在某些情况下会失败,例如for 循环会改变长度。
    【解决方案2】:

    只是为了详细说明@Brand 的答案,你可以这样做:

    var vid = document.getElementById("frag1"); // set video to variable
    var buttons = document.getElementsByTagName("button"); // element collection
    for (var i = 0; i < buttons.length; i++) { // run for loop
      buttons[i].addEventListener("click", function() { // add event listenr
        var dataStart = this.getAttribute('data-start'); // extract start time
        var dataEnd = this.getAttribute('data-end'); // extract end time
        var dataDuration = Number(dataEnd - dataStart + '000'); // make the duration will assist on the setTimeOut
        vid.currentTime = dataStart; // this is the magic
        vid.play();
        window.setTimeout(function(){ vid.pause(); }, dataDuration);// play according to duration   
      });
    }
    <section class="wrapper">
      <div>
        <video id="frag1" controls preload="metadata" width="400px">
          <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4">
          <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogg">
        </video>
        <nav>
          <button data-start="0" data-end="10">Section One</button>
          <button data-start="30" data-end="40">Section Two</button>
          <button data-start="30" data-end="60">Section Three</button>
        </nav>
      </div>
    </section>

    您可以找到有关此herehere 的更多信息。

    希望对您有所帮助。

    【讨论】:

    • 谢谢。所以这是我的问题:我可以单击运行代码 sn-p,它看起来可以在这个页面上运行,但是当我复制到我的文件时它突然不起作用。我会阅读您链接的参考资料,但您知道为什么这不起作用吗?你上面写的就是我想做的。
    • 是的,我对 dataDuration 有误 - 忘记添加“000”。现在检查。
    • 嗨。是的,我现在正在看它。我正在尝试,但它仍然无法正常工作。页面加载,但按钮没有响应。不过我会继续玩它的。
    • 如果我单击此页面上的“运行代码 sn-p”它可以工作,但是如果我将其复制到我的 html 编辑程序并使用 python -m SimpleHTTPServer 通过终端加载页面它不起作用...
    • 我刚刚检查了控制台,但它没有给我任何错误消息,按钮不起作用。
    【解决方案3】:

    这比你想的要容易。只需设置currentTime 属性即可。

    未经测试,但这应该可以帮助您入门:

    document.querySelector('nav').addEventListener('click', (e) => {
      if (!e.target.matches('[data-start]')) {
        return;
      }
      document.querySelector('video').currentTime = Number.parseFloat(e.target.dataset.start);
    });
    

    【讨论】:

    • 非常感谢,但我想这超出了我的想象。我一直在尝试遵循该教程,我同意它似乎比它需要的更复杂。我不明白为什么它在 codepen 中有效,但在我复制和粘贴时无效。感谢您尝试提供帮助,我欢迎任何替代方法来实现它,但老实说,我不确定如何处理您键入的代码。我尝试将其粘贴到我的 js 文件中,但没有成功。
    • @epignosis567 这段代码有错误。解决它。这段代码所做的只是为nav 元素添加一个click 处理程序,如果其中的任何按钮被单击,它将被触发。 (然后,我们通过检查 data-start 属性的事件目标 [what was clicked] 来确保它是被点击的按钮之一。)然后,我们只需将视频元素的 currentTime 设置为data-start 属性中的数字。 (可通过dataset 属性访问。)
    • 谢谢,我非常感谢您的帮助,但它仍然无法在我的最终工作。我现在正试图弄清楚。
    • 控制台给我这个消息:Uncaught SyntaxError: missing ) after argument list script.js:2
    • @epignosis567 修正了另一个错字...注意[data-start] 的括号在字符串之外。
    猜你喜欢
    • 2015-06-21
    • 2017-06-18
    • 2013-06-02
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 2014-09-27
    相关资源
    最近更新 更多