Reputation: 23
I'm trying to fire an event when video playback has reached 100%.
When the video is not looped, I get (currentTime/duration * 100 === 100) as true. When the video is on loop, I never get 100.
Any suggestions?
Here's the HTML.
<h3>Without Loop</h3>
<div>Current: <span id="console2"></span></div>
<div>Has hit 100%: <span id="hundredIsTrue2" class="red">No</span></div>
<video id="video2" autoplay>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
<source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg" />
</video>
<h3>With Loop</h3>
<div>Current: <span id="console"></span></div>
<div>Has hit 100%: <span id="hundredIsTrue" class="red">No</span></div>
<video id="video" autoplay loop>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
<source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg" />
</video>
Here's the JavaScript.
var video = document.getElementById('video'),
console = document.getElementById('console'),
hundred = document.getElementById('hundredIsTrue'),
video2 = document.getElementById('video2'),
console2 = document.getElementById('console2'),
hundred2 = document.getElementById('hundredIsTrue2');
video.addEventListener('timeupdate', function (e) {
console.innerHTML = e.target.currentTime / e.target.duration * 100;
if (e.target.currentTime / e.target.duration * 100 === 100) {
hundred.className = 'green';
hundred.innerHTML = 'Yes';
}
});
video2.addEventListener('timeupdate', function (e) {
console2.innerHTML = e.target.currentTime / e.target.duration * 100;
if (e.target.currentTime / e.target.duration * 100 === 100) {
hundred2.className = 'green';
hundred2.innerHTML = 'Yes';
}
});
Here's the CSS.
.red {
background-color: red;
}
.green {
background-color: green;
}
Upvotes: 0
Views: 230
Reputation: 7853
The timeupdate
event does not actually run on every frame. It runs approximately every 250ms or 1/4 second. So it looks like what's happening here is that the last timeupdate
event fires at less than 250ms before the end of the video and then the video ends and starts over back at the beginning before there's a chance for another timeupdate
event to fire. So the next timeupdate
event that fires will report currentTime
at or close to zero.
So if you want to have your video automatically loop, there's a few things you can do to detect the end. One option is to look for a time that's sufficiently close, like maybe 0.5 second before the end. Another option is to wait for the seeked
event, which should fire as the video ends and seeks back to zero, but that won't be helpful if you also allow the user to manually seek around the video.
A third option is to disable automatic looping and listen for the ended
event. ended
fires when the video gets to the end, but only if the loop
property/attribute is not enabled. When you receive the event, you can fire your event, set currentTime
back to 0 and call .play()
again.
Upvotes: 0
Reputation: 1009
The calculated value moves from the 90s back to 0 without hitting the exact value 100. Would something like the below help? There is a possiblity of the value not hitting 99 either. Setting a smaller value like '95' might work for what you want to achieve.
if (e.target.currentTime / e.target.duration * 100 > 99) {
hundred.className = 'green';
hundred.innerHTML = 'Yes';
}
Upvotes: 0