У меня есть простой интерактивный видеоплеер HTML5, в котором пользователь может воспроизводить разные видео с помощью кнопок при нажатии.
Я добавил кнопку возврата, которая позволяет пользователю вернуться к ранее воспроизведенному видео.
Вот html
<div class = "container-fluid">
<div class = "row">
<div class = "col-12" canplay id = "video-block">
<div id = "video-container">
<video id = "videoplayer" playsinline autoplay>
<source src = "" type = "video/mp4">
</video>
<div id = "interactive-layers">
<!-- <div class = "go_back">Go back</div> -->
</div>
</div>
<div id = "video-controls">
<div id = "seek-bar-container">
<div id = "seek-bar">
<div id = "current-time">
</div>
</div>
</div>
<div id = "pause-play-button">
<span id = "play">play</span>
<span id = "pause">pause</span>
</div>
</div>
</div>
</div>
</div>
вот мой js
var movies = null;
var flowchart = null;
var connections = null;
var videohistory = [];
$(document).ready(function () {
$.getJSON('data.json', function (data) {
movies = data.movies;
$.getJSON('datasaved/settings2.json', function (data) {
flowchart = data.movies;
connections = data.connections;
for (var c = 0; c < connections.length; c++) {
connections[c].buttonid = String(connections[c].buttonid).split("moviebuttons")[1];
connections[c].movieid = String(connections[c].movieid).split("movieblock")[1];
}
for (var j = 0; j < movies.length; j++) {
for (var i = 0; i < flowchart.length; i++) {
if (flowchart[i].checkbox == true && flowchart[i].movieid == movies[j].movieid) {
playVideo(movies[j], flowchart[i]);
}
}
}
});
setInterval(updateTimeline, 40);
})
$("#interactive-layers").on("click", ".video-btns", buttonLinkClicked);
$('#interactive-layers').on('click', ".go_back", function () {
playVideo(videohistory[videohistory.length - 2], true);
});
video = $("#video-container").find('video');
video[0].addEventListener("timeupdate", onUpdateTime);
video[0].addEventListener("canplaythrough", videoReady);
video[0].addEventListener("pause", onPause);
video[0].addEventListener("play", onPlay);
video[0].addEventListener("ended", onEnded);
video[0].addEventListener("timeupdate", onUpdateTime);
})
function buttonLinkClicked(e) {
var mov = null;
var flo = null;
for (var j = 0; j < movies.length; j++) {
if ($(e.target).attr("targetmovieid") == movies[j].movieid) {
mov = movies[j];
}
}
for (var i = 0; i < flowchart.length; i++) {
if (flowchart[i].movieid == $(e.target).attr("targetmovieid")) {
flo = flowchart[i];
}
}
if (mov == null || flo == null) {
$(this).attr('buttonid');
var getButon = $(this).attr('buttonid');
switch (getButon) {
case "5":
window.open('https://www.meed.com/', '_blank').focus();
break;
case "6":
window.open('https://buy.meed.com/', '_blank').focus();
break;
case "7":
window.open('https://www.meedprojects.com/projects-platform/bespoke-services', '_blank').focus();
break;
case "60":
window.open('https://premium.meedprojects.com/Login', '_blank').focus();
break;
}
} else {
playVideo(mov, flo);
}
}
function updateTimeline() {
if ($("#videoplayer")[0].duration) {
$(".video-btns").each(function () {
if ($("#videoplayer")[0].currentTime >= parseFloat($(this).attr("starttime")) && $("#videoplayer")[0].currentTime < parseFloat($(this).attr("endtime"))) {
$(this).addClass("show");
} else {
$(this).removeClass("show");
}
});
}
}
function addGoBack() {
var goback = $(" <div class='go_back'>Go back</div>");
$("#interactive-layers").append(goback);
}
function playVideo(movie, flowchartvideo, back) {
var movieHistory = Object.values(movie);
$("#interactive-layers").html("");
addGoBack();
if (back == true) {
videohistory.pop();
} else {
videohistory.push(movieHistory);
console.info(videohistory);
}
if (videohistory.length == 1) {
$(".go_back").addClass('hidden');
} else {
$(".go_back").removeClass('hidden');
}
var buttons = movie.buttons;
for (var b = 0; b < buttons.length; b++) {
for (var c = 0; c < connections.length; c++) {
if (connections[c].buttonid == buttons[b].buttonid) {
buttons[b].targetmovieid = connections[c].movieid;
}
}
}
$("#videoplayer").attr("src", movie.movie_url);
$("#videoplayer")[0].muted = false;
// alert(buttons.length);
for (var b = 0; b < buttons.length; b++) {
var buttonid = buttons[b].buttonid;
var label = buttons[b].label;
var starttime = buttons[b].start_time;
var endtime = buttons[b].end_time;
var videobtns = $("<div buttonid='" + buttonid + "' class='video-btns' targetmovieid='" + buttons[b].targetmovieid + "' starttime='" + starttime + "' endtime='" + endtime + "'><span class='label'>" + label + "</span></div>")
var top, left, width, height;
top = buttons[b].top
left = buttons[b].left
width = buttons[b].width
height = buttons[b].height;
$("#interactive-layers").append(videobtns);
videobtns.css({
top: top,
left: left,
width: width,
height: height
})
}
}
Когда пользователь воспроизводит второе видео, появляется кнопка возврата, и пользователь может щелкнуть ее и воспроизвести предыдущий фильм.
Теперь, когда я нажимаю вернуться, я получаю следующую ошибку
main.js: 156 Uncaught TypeError: невозможно прочитать свойство «длина» неопределенного
ОБНОВИТЬ
Here is live demo : live demo
Что я делаю неправильно? или может кто-нибудь предоставить простой метод для этого?
Какая строка является строкой 156?
for (var b = 0; b < buttons.length; b++)@Barmar Я не добавляю соединения, потому что с этим нет проблем, я просто хочу воспроизвести предыдущее воспроизведенное видео, но не уверен, что делаю правильно
@Barmar добавил весь код, который я использую для своего плеера и живой демонстрации
Ошибка означает, что movie.buttons не определено. Проверьте значение movie.
@Barmar на консоли movie.buttons перед нажатием кнопки возврата отображает значение, сразу после нажатия кнопки возврата отображается эта ошибка, вы можете проверить это в демо-версии.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я ответил очень быстро, после проверки вашего рабочего кода, предлагаю вам внимательнее взглянуть на строку...
var movieHistory = Object.values(movie);
Похоже, он не делает то, что вы хотите. (клонировать объект фильма). Просто измените его на
var movieHistory = movie;
У меня это работает в консоли Chrome Dev...
Я попробую вот живая демо https://videomill-bot.audiencevideo.com/editor/preview.html проверьте это
У меня есть весь код, который я использую, проверьте обновленный вопрос, эта строка предназначена для преобразования объекта в массив, проверьте код
да, он преобразует объект в массив, но это создаст проблему при следующем вызове функции. Он ожидает объект, но теперь получает массив.
ради интереса попробуйте изменить "var movieHistory = Object.values(movie);" на "var movieHistory = фильм"
что эта строка должна делать?
Вы хотите сохранить ранее показанное видео в массиве, чтобы иметь возможность вернуться к нему, но только потому, что вам нужен объект в массиве, это не причина для преобразования его в один. просто поместите исходный объект фильма в массив истории, он будет работать.
@user9964622 user9964622 Это должно было быть очевидно, если бы вы это сделали console.info(videohistory). Он не содержит массив объектов.
У вас нигде нет переменной
connections, что такоеconnections.length?