Reputation: 3280
So I'm trying to make an object that handles an HTML video by making it pause when it reaches certain second marks. At every pause there is some type of "next" button that then resumes the video. My nicely commented code should make it more clear what I'm trying to achieve.
HTML:
<div class="fancyvid">
<video preload="auto" poster="assets/myposter.png" id="ssvid">
<source src="assets/myvideo.mp4" type="video/mp4" />
</video>
<div class="textlayer" data-pauseat="5">
<h1>First pause (5 seconds)</h1>
<p>Here's some text for the first pause event</p>
<button class="next-btn">Next</button>
</div>
<div class="textlayer" data-pauseat="11">
<h1>Second pause (11 seconds)</h1>
<p>Here's some text for the second pause event</p>
<button class="next-btn">Next</button>
</div>
<div class="textlayer" data-pauseat="15">
<h1>Third pause (15 seconds)</h1>
<p>Here's some text for the third pause event</p>
<button class="next-btn">Next</button>
</div>
</div>
<div class="button-holder">
<button id="video-play">Play Interactive Video</button>
<script type="text/javascript">
$(function(){
$('#video-play').click(function () {
VidHandler.PlayFromBeginning();
$(this).remove();
});
})
</script>
</div>
Other JavaScript:
$(function(){
window.VidHandler = (function (vidId) {
// refrence to VidHandler for passing into certain scopes
var that = this;
// get video DOM element
this.videlem = $('#' + vidId)[0];
// get container
this.$container = $(this.videlem).closest('div.fancyvid');
// get the reused "Next" button
this.$nextbtn = this.$container.find('.next-button');
// start tick at zero
this.tick = this.videlem.currentTime;
// add event listener to video for time events
this.videlem.addEventListener('timeupdate',function(e){
console.log('currentTime: ' + that.tick); // TEST
var pfunc = that.PauseFunctions[that.tick];
if ( pfunc !== undefined ) // if there is a pause function corresponding to this second
{
that.videlem.pause();
pfunc();
}
else
{
++that.tick;
}
//
}, false);
// plays video from beginning
this.PlayFromBeginning = function ( ) {
this.videlem.currentTime = 0;
this.videlem.play();
}
// returns a jQuery element of the HTML layer
// associated with a particular second mark
this.GetLayerElement = function ( secondMark )
{
return this.$container.find('div.textlayer[data-pauseat="' + secondMark + '"]');
}
// maps second indices in the video to events
// that are called when the video pauses at that second
this.PauseFunctions = {
5: function () {
var $layer = that.GetLayerElement(5);
$layer.show();
var $nextbtn = $layer.find('.next-btn');
$nextbtn.click(function () {
$layer.hide();
that.videlem.play();
});
},
11 : function () {
console.log("The pause function of the event at the 11-second mark was called");
},
15: function () {
console.log("The pause function of the event at the 10-second mark was called");
}
};
return this;
})("ssvid");
});
The main problem I'm facing at the moment is that my
this.videlem.addEventListener('timeupdate',function(e){
event seems to not be firing evenly.
As a test, I did
var first_millmark = new Date();
// add event listener to video for time events
this.videlem.addEventListener('timeupdate',function(e){
console.log('currentTime: ' + that.tick); // TEST
console.log("Milliseconds past: " + (new Date() - first_millmark));//TEST
and the output was
vidpage.js:23 currentTime: 0 vidpage.js:24 Milliseconds past: 2279
vidpage.js:23 currentTime: 1 vidpage.js:24 Milliseconds past: 2777
vidpage.js:23 currentTime: 2 vidpage.js:24 Milliseconds past: 3277
vidpage.js:23 currentTime: 3 vidpage.js:24 Milliseconds past: 3527
vidpage.js:23 currentTime: 4 vidpage.js:24 Milliseconds past: 4027
vidpage.js:23 currentTime: 5 vidpage.js:24 Milliseconds past: 4276
vidpage.js:23 currentTime: 5 vidpage.js:24 Milliseconds past: 4281
Yikes! What's going wrong? And is an entirely better way of implementing this pattern that I'm trying to implement?
Upvotes: 2
Views: 102
Reputation: 64725
timeupdate does not fire once per second:
The event frequency is dependant on the system load, but will be thrown between about 4Hz and 66Hz (assuming the event handlers don't take longer than 250ms to run). User agents are encouraged to vary the frequency of the event based on the system load and the average cost of processing the event each time, so that the UI updates are not any more frequent than the user agent can comfortably handle while decoding the video.
https://developer.mozilla.org/en-US/docs/Web/Events/timeupdate
What you need to do instead, is look at the time indicated by the currentTime
attribute when the event has fired, and see if it is greater than or equal to the time of a pause point that has not been triggered yet.
this.pausePoints = [
{second: 5, func: function() { /* whatever */ },
{second: 15, func: function() { /* whatever */ }
//etc.
];
this.videlem.addEventListener('timeupdate',function(e){
if (this.pausePoints.length && this.videlem.currentTime > this.pausePoints[0].seconds) {
var pausePoint = this.pausePoints.shift();
pausePoint.func();
this.videlem.pause();
}
}.bind(this), false);
Upvotes: 1
Reputation: 1384
Anything can delay the process of javascript, from the memory JS utilize alone to your computer being slow.
But based on your question:
So I'm trying to make an object that handles an HTML video by making it pause when it reaches certain second marks
I would suspect this function would do the trick nicely, I would return it as soon as possible until you've reached a point in which your video should pause.
so, for example:
timesToPause=[100,1000,10000];
function check_timer(cTime){ //return true
if(cTime >= timesToPause[0]){
timesToPause.splice(0, 1); //Remove this timer from timesToPause;
pauseVideo(); // whatever your function is to pause the video or run your
return true;
}
return false;
}
Now, I've not fully tested this, but the code should pause the video at the timer specified. If, for example, you start the video at 1200 seconds, it would pause the video twice, hitting both timers of 100 and 1000; You may want to add a loop in the remove section incase they skip it, so it only plays once.
Upvotes: 2