add a toggle for maximizing videos with numbers on the keyboard
This commit is contained in:
parent
5082cf31b6
commit
82482b8778
2 changed files with 149 additions and 3 deletions
46
index.html
46
index.html
|
@ -45,6 +45,52 @@
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
grid-template-rows: 1fr 1fr;
|
grid-template-rows: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Maximized view layout */
|
||||||
|
.video-container.maximized {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container.maximized .main-video {
|
||||||
|
width: 80%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container.maximized .side-videos {
|
||||||
|
width: 20%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container.maximized .side-videos .video-wrapper {
|
||||||
|
position: relative;
|
||||||
|
height: 150px;
|
||||||
|
min-height: 150px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container.maximized .side-videos video {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-number-label {
|
||||||
|
font-family: "Helvetica", "Arial", sans-serif;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
z-index: 10;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
|
||||||
video {
|
video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
106
src/main.ts
106
src/main.ts
|
@ -7,6 +7,8 @@ type VideoConfig = {
|
||||||
|
|
||||||
let videos: VideoConfig[] = [];
|
let videos: VideoConfig[] = [];
|
||||||
let videoElements: HTMLVideoElement[] = [];
|
let videoElements: HTMLVideoElement[] = [];
|
||||||
|
let isMaximizedView = false;
|
||||||
|
let maximizedVideoIndex = -1;
|
||||||
|
|
||||||
// Initialize the video grid
|
// Initialize the video grid
|
||||||
async function initialize(url: string) {
|
async function initialize(url: string) {
|
||||||
|
@ -204,12 +206,110 @@ function onTimeUpdate(event: Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to toggle maximized view for a specific video
|
||||||
|
function toggleMaximizedView(index: number) {
|
||||||
|
const container = document.getElementById("videoContainer");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
// If we're already in maximized view and trying to maximize the same video, do nothing
|
||||||
|
if (isMaximizedView && maximizedVideoIndex === index) return;
|
||||||
|
|
||||||
|
// If we're trying to restore grid view (index === -1)
|
||||||
|
if (index === -1) {
|
||||||
|
if (!isMaximizedView) return; // Already in grid view
|
||||||
|
|
||||||
|
// Remove maximized class and restore grid class
|
||||||
|
container.classList.remove("maximized");
|
||||||
|
container.classList.add(`count-${videos.length}`);
|
||||||
|
|
||||||
|
// Remove any wrapper divs and restore original structure
|
||||||
|
while (container.firstChild) {
|
||||||
|
container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-add all videos directly to the container
|
||||||
|
videoElements.forEach(video => {
|
||||||
|
container.appendChild(video);
|
||||||
|
});
|
||||||
|
|
||||||
|
isMaximizedView = false;
|
||||||
|
maximizedVideoIndex = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the index is out of range, do nothing
|
||||||
|
if (index < 0 || index >= videoElements.length) return;
|
||||||
|
|
||||||
|
// Switch to maximized view
|
||||||
|
container.classList.remove(`count-${videos.length}`);
|
||||||
|
container.classList.add("maximized");
|
||||||
|
|
||||||
|
// Clear the container
|
||||||
|
while (container.firstChild) {
|
||||||
|
container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create main video div
|
||||||
|
const mainVideoDiv = document.createElement("div");
|
||||||
|
mainVideoDiv.className = "main-video";
|
||||||
|
mainVideoDiv.appendChild(videoElements[index]);
|
||||||
|
container.appendChild(mainVideoDiv);
|
||||||
|
|
||||||
|
// Create side videos div
|
||||||
|
const sideVideosDiv = document.createElement("div");
|
||||||
|
sideVideosDiv.className = "side-videos";
|
||||||
|
container.appendChild(sideVideosDiv);
|
||||||
|
|
||||||
|
// Add all other videos to side videos div with number labels
|
||||||
|
videoElements.forEach((video, i) => {
|
||||||
|
if (i !== index) {
|
||||||
|
// Create a wrapper for the video and label
|
||||||
|
const videoWrapper = document.createElement("div");
|
||||||
|
videoWrapper.className = "video-wrapper";
|
||||||
|
|
||||||
|
// Add the video to the wrapper
|
||||||
|
videoWrapper.appendChild(video);
|
||||||
|
|
||||||
|
// Create and add the number label
|
||||||
|
const numberLabel = document.createElement("div");
|
||||||
|
numberLabel.className = "video-number-label";
|
||||||
|
numberLabel.textContent = String(i + 1); // 1-based indexing for display
|
||||||
|
videoWrapper.appendChild(numberLabel);
|
||||||
|
|
||||||
|
// Add the wrapper to the side videos div
|
||||||
|
sideVideosDiv.appendChild(videoWrapper);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
isMaximizedView = true;
|
||||||
|
maximizedVideoIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle keyboard events
|
||||||
|
function handleKeyPress(event: KeyboardEvent) {
|
||||||
|
// Check if the key pressed is a number
|
||||||
|
const key = event.key;
|
||||||
|
if (/^[0-9]$/.test(key)) {
|
||||||
|
const num = parseInt(key, 10);
|
||||||
|
if (num === 0) {
|
||||||
|
// Restore grid view
|
||||||
|
toggleMaximizedView(-1);
|
||||||
|
} else if (num <= videoElements.length) {
|
||||||
|
// Maximize the corresponding video (1-based indexing for user, 0-based for array)
|
||||||
|
toggleMaximizedView(num - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize everything when the page loads
|
// Initialize everything when the page loads
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
try {
|
try {
|
||||||
initialize("content/data.json");
|
await initialize("content/data.json");
|
||||||
|
|
||||||
|
// Add keyboard event listener
|
||||||
|
document.addEventListener("keydown", handleKeyPress);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error("Failed to initialize:", err);
|
||||||
alert(`Failed to load videos: ${err}`);
|
alert(`Failed to initialize: ${err}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue