Refine progress bar positioning and styling in VideoJSPlayer

Enhanced the logic for moving and styling the progress bar relative to the control bar, including improved style resets and visibility transitions. Updated the default non-touch progress bar position from 'top' to 'bottom' in playerConfig.js for a more native touch style experience.
This commit is contained in:
Yiannis Christodoulou 2025-10-10 01:20:09 +03:00
parent 4acdec7474
commit 59f65bdd21
2 changed files with 88 additions and 78 deletions

View File

@ -2546,96 +2546,106 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
// BEGIN: Move progress bar below control bar (native touch style) // BEGIN: Move progress bar below control bar (native touch style)
setTimeout(() => { setTimeout(() => {
if (actualPosition === 'bottom' || actualPosition === 'top') { if (
if (progressControl && progressControl.el() && controlBar && controlBar.el()) { (actualPosition === 'bottom' || actualPosition === 'top') &&
const progressEl = progressControl.el(); progressControl &&
const controlBarEl = controlBar.el(); progressControl.el() &&
controlBarEl.style.gap = 0; controlBar &&
controlBar.el()
) {
const progressEl = progressControl.el();
const controlBarEl = controlBar.el();
controlBarEl.style.gap = 0;
controlBarEl.style.background = 'none';
progressEl.style.background = 'none';
// Remove progress control from control bar // Remove progress control from control bar
controlBar.removeChild(progressControl); controlBar.removeChild(progressControl);
// Create a wrapper div that will hold both progress and control bar // Create a wrapper div that will hold both progress and control bar
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
wrapper.className = 'vjs-controls-wrapper'; wrapper.className = 'vjs-controls-wrapper';
wrapper.style.position = 'absolute'; wrapper.style.position = 'absolute';
wrapper.style.bottom = '0'; wrapper.style.bottom = '0';
wrapper.style.left = '0'; wrapper.style.left = '0';
wrapper.style.right = '0'; wrapper.style.right = '0';
wrapper.style.width = '100%'; wrapper.style.width = '100%';
// Insert wrapper before control bar // Insert wrapper before control bar
controlBarEl.parentNode.insertBefore(wrapper, controlBarEl); controlBarEl.parentNode.insertBefore(wrapper, controlBarEl);
// Position elements based on actual resolved position // Position elements based on actual resolved position
if (actualPosition === 'top') { if (actualPosition === 'top') {
// Progress bar above control bar // Progress bar above control bar
wrapper.appendChild(progressEl); wrapper.appendChild(progressEl);
wrapper.appendChild(controlBarEl); wrapper.appendChild(controlBarEl);
} else {
// Progress bar below control bar (bottom/native style)
wrapper.appendChild(controlBarEl);
wrapper.appendChild(progressEl);
}
// Style the progress control using config values
progressEl.style.position = 'relative';
progressEl.style.width = '100%';
progressEl.style.height = '15px';
progressEl.style.margin = '8px 0'; // Add top and bottom margin
progressEl.style.padding = '5px 10px'; // Add left and right padding/gap
progressEl.style.display = 'block';
progressEl.style.transition = 'opacity 0.3s, visibility 0.3s'; // Smooth transition
progressEl.style.boxSizing = 'border-box'; // Ensure padding doesn't increase width
// Style control bar positioning
controlBarEl.style.position = 'relative';
controlBarEl.style.width = '100%';
// Store reference for cleanup
customComponents.current.movedProgressControl = progressControl;
customComponents.current.controlsWrapper = wrapper;
// Hide/show progress bar with control bar based on user activity
const syncProgressVisibility = () => {
const isControlBarVisible =
controlBar.hasClass('vjs-visible') ||
!playerRef.current.hasClass('vjs-user-inactive');
if (isControlBarVisible) {
progressEl.style.opacity = '1';
progressEl.style.visibility = 'visible';
} else { } else {
// Progress bar below control bar (bottom/native style) progressEl.style.opacity = '0';
wrapper.appendChild(controlBarEl); progressEl.style.visibility = 'hidden';
wrapper.appendChild(progressEl);
} }
};
// Style the progress control using config values // Listen to user activity events
progressEl.style.position = 'relative'; playerRef.current.on('useractive', syncProgressVisibility);
progressEl.style.width = '100%'; playerRef.current.on('userinactive', syncProgressVisibility);
progressEl.style.height = '15px';
progressEl.style.margin = '8px 0'; // Add top and bottom margin
progressEl.style.padding = '5px 10px'; // Add left and right padding/gap
progressEl.style.display = 'block';
progressEl.style.transition = 'opacity 0.3s, visibility 0.3s'; // Smooth transition
progressEl.style.boxSizing = 'border-box'; // Ensure padding doesn't increase width
// Style control bar positioning // Initial sync
controlBarEl.style.position = 'relative'; syncProgressVisibility();
controlBarEl.style.width = '100%';
// Store reference for cleanup if (isEmbedPlayer) {
customComponents.current.movedProgressControl = progressControl;
customComponents.current.controlsWrapper = wrapper;
// Hide/show progress bar with control bar based on user activity
const syncProgressVisibility = () => {
const isControlBarVisible =
controlBar.hasClass('vjs-visible') ||
!playerRef.current.hasClass('vjs-user-inactive');
if (isControlBarVisible) {
progressEl.style.opacity = '1';
progressEl.style.visibility = 'visible';
} else {
progressEl.style.opacity = '0';
progressEl.style.visibility = 'hidden';
}
};
// Listen to user activity events
playerRef.current.on('useractive', syncProgressVisibility);
playerRef.current.on('userinactive', syncProgressVisibility);
// Initial sync
syncProgressVisibility();
// Initial sync - hide until video starts // Initial sync - hide until video starts
progressEl.style.opacity = '0'; progressEl.style.opacity = '0';
progressEl.style.visibility = 'hidden'; progressEl.style.visibility = 'hidden';
// Show when video starts
const showOnPlay = () => {
syncProgressVisibility();
playerRef.current.off('play', showOnPlay);
playerRef.current.off('seeking', showOnPlay);
};
playerRef.current.on('play', showOnPlay);
playerRef.current.on('seeking', showOnPlay);
// Store cleanup function
customComponents.current.cleanupProgressVisibility = () => {
playerRef.current.off('useractive', syncProgressVisibility);
playerRef.current.off('userinactive', syncProgressVisibility);
};
} }
// Show when video starts
const showOnPlay = () => {
syncProgressVisibility();
playerRef.current.off('play', showOnPlay);
playerRef.current.off('seeking', showOnPlay);
};
playerRef.current.on('play', showOnPlay);
playerRef.current.on('seeking', showOnPlay);
// Store cleanup function
customComponents.current.cleanupProgressVisibility = () => {
playerRef.current.off('useractive', syncProgressVisibility);
playerRef.current.off('userinactive', syncProgressVisibility);
};
} }
}, 100); }, 100);

View File

@ -12,7 +12,7 @@ const PlayerConfig = {
// 'default' - use Video.js default positioning (inside control bar) // 'default' - use Video.js default positioning (inside control bar)
// 'top' - progress bar above control bar // 'top' - progress bar above control bar
// 'bottom' - progress bar below control bar // 'bottom' - progress bar below control bar
nonTouchPosition: 'top', nonTouchPosition: 'bottom',
// Position for touch devices: 'top' or 'bottom' (no 'default' option) // Position for touch devices: 'top' or 'bottom' (no 'default' option)
// 'top' - progress bar above control bar // 'top' - progress bar above control bar