当用户观看视频时,我想进行2次AJAX通话。一个用户完成观看视频并且播放的时间等于或大于视频的持续时间(因为用户也可以倒带)。 timePlayed>=duration && event.type=="ended"
。我成功地接听了这个电话。
我努力的地方是,当观看视频超过80%并且视频播放时间超过80%时,我还想拨打电话,以防止用户快速转发。
为了使其工作,我必须修改我的videoStartedPlaying()
方法,这是我遇到问题的地方,因为我正在尝试设置间隔。现在,通过设置间隔,它就像一个无限循环。
var video_data = document.getElementById("video");
var timeStarted = -1;
var timePlayed = 0;
var duration = 0;
// If video metadata is loaded get duration
if(video_data.readyState > 0)
getDuration.call(video_data);
//If metadata not loaded, use event to get it
else {
video_data.addEventListener('loadedmetadata', getDuration);
}
// remember time user started the video
function videoStartedPlaying() {
timeStarted = new Date().getTime()/1000;
setInterval(function(){
playedFor = new Date().getTime()/1000 - timeStarted;
checkpoint = playedFor / duration;
percentComplete = video_data.currentTime/video_data.duration;
// here I need help of how to best accomplish this
if (percentComplete >= 0.8 && checkpoint >= 0.8) {
// AJAX call here
}
}, 2000);
}
function videoStoppedPlaying(event) {
// Start time less then zero means stop event was fired vidout start event
if(timeStarted>0) {
var playedFor = new Date().getTime()/1000 - timeStarted;
timeStarted = -1;
// add the new amount of seconds played
timePlayed+=playedFor;
}
// Count as complete only if end of video was reached
if(timePlayed>=duration && event.type=="ended") {
// AJAX call here
}
}
function getDuration() {
duration = video_data.duration;
}
video_data.addEventListener("play", videoStartedPlaying);
video_data.addEventListener("playing", videoStartedPlaying);
video_data.addEventListener("ended", videoStoppedPlaying);
video_data.addEventListener("pause", videoStoppedPlaying);
我真的很感激任何有关这方面的帮助,因为我似乎在我的智慧结束。
非常感谢!
编辑: 感谢评论,我想出了这个:
const video = document.getElementById("video");
const set = new Set();
const percent = .8;
let toWatch;
function mediaWatched (curr) {
alert(`${curr}% of media watched`)
}
function handleMetadata(e) {
toWatch = Math.ceil(video.duration * percent);
console.log(toWatch, video.duration);
}
function handleTimeupdate (e) {
set.add(Math.ceil(video.currentTime));
let watched = Array.from(set).pop();
if (set.has(toWatch) && watched === toWatch) {
video.removeEventListener("timeupdate", handleTimeupdate);
console.log(watched);
mediaWatched(
Math.round(watched / Math.ceil(video.duration) * 100)
);
}
}
video.addEventListener("loadedmetadata", handleMetadata);
video.addEventListener("timeupdate", handleTimeupdate);
<video width="400" height="300" controls="true" poster="" id="video">
<source type="video/mp4" src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4" />
</video>
现在,例如,如果我快进到大约50%的长度,然后让它播放,它会在80%的电影到达时触发,但它不应该因为我快速转发到50%而且基本上只看了30%。
这有意义吗?我怎样才能实现这种行为?
答案 0 :(得分:2)
这里的评论讨论是一个工作样本。
它包含一些处理程序,只是为了让您在设置数组和总结内容时更轻松,因此您知道何时达到80%标记(尽管如果您想强制它们,您可能需要更改该逻辑比方说,在整个视频中,明确观察前80%,而不仅仅是80%。
在那里有许多console.log(...)
语句,因此您可以在浏览器控制台窗口中观察它正在做什么...您可能希望在部署为真实之前将其取出。
我已经在timeupdate
事件中找到了在哪里进行ajax调用,但你总是可以在主循环中使用常规setInterval
计时器来检查80%并在那里打电话,但这看起来更干净
大部分都应该是自我解释的,但如果有任何不清楚的地方,请在评论中询问......
<video controls preload="auto" id="video" width="640" height="365" muted>
<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4" type="video/mp4">
</video>
<script>
// handler to let me resize the array once we know the length
Array.prototype.resize = function(newSize, defaultValue) {
while(newSize > this.length)
this.push(defaultValue);
this.length = newSize;
}
// function to round up a number
function roundUp(num, precision) {
return Math.ceil(num * precision) / precision
}
var vid = document.getElementById("video")
var duration = 0; // will hold length of the video in seconds
var watched = new Array(0);
var reported80percent = false;
vid.addEventListener('loadedmetadata', getDuration, false);
vid.addEventListener('timeupdate',timeupdate,false)
function timeupdate() {
currentTime = parseInt(vid.currentTime);
// set the current second to "1" to flag it as watched
watched[currentTime] = 1;
// show the array of seconds so you can track what has been watched
// you'll note that simply looping over the same few seconds never gets
// the user closer to the magic 80%...
console.log(watched);
// sum the value of the array (add up the "watched" seconds)
var sum = watched.reduce(function(acc, val) {return acc + val;}, 0);
// take your desired action on the ?80% completion
if ((sum >= (duration * .8)) && !reported80percent) {
// set reported80percent to true so that the action is triggered once and only once
// could also unregister the timeupdate event to avoid calling unneeded code at this point
// vid.removeEventListener('timeupdate',timeupdate)
reported80percent = true;
console.log("80% watched...")
// your ajax call to report progress could go here...
}
}
function getDuration() {
console.log("duration:" + vid.duration)
// get the duration in seconds, rounding up, to size the array
duration = parseInt(roundUp(vid.duration,1));
// resize the array, defaulting entries to zero
console.log("resizing arrary to " + duration + " seconds.");
watched.resize(duration,0)
}
</script>