简体   繁体   中英

HTML5 video media fragments with Javascript

No one on here ever comments on my questions but maybe this is an easy one? I'm new to coding and I am trying to find a way to navigate a video, as in play the first 10 seconds then stop, play seconds 30-40 then stop, play second 60-30 then stop, etc and to have buttons for it. I have found a tutorial but the buttons don't respond. I've cleaned up the code a bit (don't think I removed anything necessary) and pasted it below. Tutorial link: 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();

Use Event Delegation when you have multiple tags to click.

  1. Find an ancestor tag (ex. <nav> ) that all of the target tags (ex. <a> ) have in common. Register the ancestor tag to the event. Now whenever the ancestor tag or its descendant tags triggers the registered event, the callback function bound to the ancestor tag will fire. So essentially that's one event listener for an unlimited number of target tags.

     document.querySelector(ancestor).addEventListener('click', callback);
  2. Always have callback function pass the Event Object .

     function callback(event) {...
  3. Determine the tag that is the origin of event (button clicked, video time updated, etc...) by referencing Event.target .

     const clicked = event.target
  4. In the callback function it should only apply to the target tags and exclude all other tags.

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

Details commented in 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>

This is easier than you're making it to be. Just set the currentTime property.

Untested, but this should get you started:

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

Just to elaborate @Brand answer, you can do it like that:

 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>

You can find a lot more information about this here and here .

Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM