I’m a beginner with javascript and I managed to merge two functions controlling video play, however, they interfere with each other a bit.
This function is supposed to provide custom pause and play video controls
// VIDEO CONTROLS START
const video = document.getElementById("heroVideo"),
pauseControl = document.getElementById("pauseControl"),
playControl = document.getElementById("playControl"),
playPauseButton = document.getElementById("playPauseButton");
playPauseButton.addEventListener("click", function () {
if (video.paused) {
video.play();
playPauseButton.classList.remove("play");
playPauseButton.classList.add("pause");
pauseControl.style.display = "unset";
playControl.style.display = "none";
} else {
video.pause();
playPauseButton.classList.remove("pause");
playPauseButton.classList.add("play");
pauseControl.style.display = "none";
playControl.style.display = "unset";
video.removeAttribute("controls");
}
});
// VIDEO CONTROLS END
And this one pauses and plays video automaticaly when out of user’s view field (so it does not play on the background)
// VIDEO OFFLOAD START
function videoOffload() {
// Get all video elements with the "video-offload" class
const videos = document.querySelectorAll(".video-offload");
// Function to handle the Intersection Observer for a single video
function handleVideoIntersection(video) {
// Define the options for the Intersection Observer
const options = {
root: null, // Use the viewport as the root
rootMargin: "0px", // No margin
threshold: 0.1, // 10% of the target element must be visible to trigger
};
// Callback function when the video enters or exits the viewport
const callback = (entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// The video is in the viewport, so play it and show controls
video.play();
video.removeAttribute("controls");
} else {
// The video is out of the viewport, so pause it and hide controls
video.pause();
}
});
};
// Create an Intersection Observer with the specified options and callback for the current video
const observer = new IntersectionObserver(callback, options);
// Start observing the current video element
observer.observe(video);
}
// Iterate over all video elements and apply the Intersection Observer
videos.forEach((video) => {
video.setAttribute("autoplay", "false"); // Disable autoplay initially
// Apply Intersection Observer to the current video
handleVideoIntersection(video);
});
}
// Call the videoOffload function to initialize
videoOffload();
// VIDEO OFFLOAD END
Video control button
<button id="playPauseButton" class="play">
<i id="playControl" class="fa-regular fa-circle-play fa-xl"></i>
<i id="pauseControl" class="fa-regular fa-circle-pause fa-xl"></i>
</button>
The issue is, as soon as I pause the video manually (utilising the first function) scroll out of the field of view of the video and then scroll back to the video again it resumes playing (the second function overcalls the first one). That is fine, however, the video control icons are reversed and you need to click twice – to pause and then play according to the pause & play function logic (because they change on click and the video was triggered by another function).
They are both in the same js file. I tried to keep them separately but the issue persisted.
I also tried to inject the icons to the HTML according to the IF statements – playPauseButton.innerHTML = "<i id='pauseControl' class='fa-regular fa-circle-pause fa-xl'></i>";
that did not work however.
The solution crossing my mind is to have them as indicators of the current state of the video – playing or paused, so no matter how the video was triggered, it is going to display the right icon OR make those two functions not interfere with each other.
What do you think is the best solution and code?
2
Answers
Okay, I made the icon functionality to work with using the event listener for a video play or pause. I also did some tweaks with a state variable that tracks whether the video was paused by the user or by the videoOffload() as advised. Right now the video pause and play works well, however, the visible icon is only the default pause one, not switching to play after pausing the video. So this statement would not been executed:
Consider refactoring the controls management to an event listener on the
video
element. This will be the most accurate source-of-truth to whether the video is playing or not: