javascript - Stepping through a video file with reveal.js -
problem , question
in reveal.js presentation, want include long video file. want have playblack stop @ positions, have time explain audience they’re seeing. then, want have playback continue when click. how can this?
unsuccessful attempts far
my attempts follows. split video file parts 1.webm
, 2.webm
, 3.webm
, on, such each part ends want have break. idea to
override keydown event of reveal.js doesn’t go next slide, instead executes javascript. how can this?
<div class="slides"> <section class="video-stepper"> <video> <source data-src="1.webm" type="video/webm" /> </video> </section> </div> <script> $(function() { // how can this? reveal.addeventlistener('click', function(event) { if ($(event.currentslide).hasclass('video-stepper')) { event.preventdefault(); // change 'src' of video element , start playback. } }); }); </script>
use fragments , autoplay video when shown:
<div class="slides"> <section class="video-stepper"> <video class="fragment current-visible video-step"> <source data-src="1.webm" type="video/webm" /> </video> <video class="fragment current-visible video-step"> <source data-src="2.webm" type="video/webm" /> </video> <video class="fragment current-visible video-step"> <source data-src="3.webm" type="video/webm" /> </video> </section> </div> <script> $(function() { reveal.addeventlistener('fragmentshown', function(event) { if ($(event.fragment).hasclass('video-step')) { event.fragment.play(); } }); }); </script>
and css taken question hide reveal.js fragments after appearance, fragments stack on top of each other:
.fragment.current-visible.visible:not(.current-fragment) { display: none; height:0px; line-height: 0px; font-size: 0px; }
however, comes fading in , out, looks bad. how can avoid fading?
when entering video slide, can disable reveal.js calling reveal.disableeventlisteners()
, bind own logic keydown event until you’ve stepped through videos, before enabling reveal.js again reveal.addeventlisteners()
.
some additional effort required avoid flickering when transitioning next video. can add new <video>
element new video, place on top of current <video>
of css z-index
, play new video, remove old.
html
<section class="video-stepper"> <!-- unlike other <video> element, 1 not absolutely positioned. hide css, use reserve space on slide , compute optimal width , height. --> <video class="placeholder stretch"> <source src="1.webm"> </video> <video class="video-step" data-sources='["1.webm","2.webm","3.webm"]'></video> </section>
css
.video-stepper { position: relative; } video.video-step { position: absolute; top: 0; left: 0; } video.video-step.front { z-index: 10; } video.placeholder { visibility: hidden; }
javascript
this bit lengthy, works desired.
reveal.addeventlistener('slidechanged', function(event) { if ($(event.currentslide).hasclass('video-stepper')) { // when enter slide step-by-step video, stop reveal.js // doing anything. below, define our own keystroke handler. reveal.removeeventlisteners(); // set width , height of video fills slide. var stretcher = $(event.currentslide).find('video.placeholder').get(0); var video = $(event.currentslide).find('video.video-step').get(0); video.setattribute('width', stretcher.getattribute('width')); video.setattribute('height', stretcher.getattribute('height')); // convert data-sources attribute array of strings. // iterate through array current_video_index. var sources = json.parse(video.getattribute('data-sources')); var current_video_index = 0; // add <source> element video , set 'src' // first video. var source = document.createelement('source'); source.setattribute('src', sources[0]); video.appendchild(source); document.addeventlistener('keydown', function step_through_videos(event) { if (event.which == 39) { // right arrow key: show next video // next video, create new <video> element // , place on top of old <video> element. // load , play new. avoids flickering. var new_video = $(video).clone().get(0); var new_video_source = $(new_video).children('source').get(0); new_video_source.src = sources[current_video_index]; new_video.load(); $(new_video).addclass('front video-step'); $(new_video).insertafter(video); new_video.play(); // wait little before removing old video. new promise((resolve) => settimeout(resolve, 500)).then(function() { video.remove(); video = new_video; $(video).removeclass('front'); }); current_video_index = current_video_index + 1; event.preventdefault(); } else if (event.which == 37) { // left arrow key: return counter previous video current_video_index = current_video_index - 1; event.preventdefault(); } if (0 > current_video_index || current_video_index >= sources.length) { // reinstall reveal.js handlers. document.removeeventlistener('keydown', step_through_videos, true); reveal.addeventlisteners(); console.log('added reveal.js event listeners.'); } }, true); } });
Comments
Post a Comment