Ursa
Ursa

Reputation: 11

Hotspot overlay for videos in fullscreen mode on web browsers

I have cooked up some code to display video overlay hotspots. However, when I make the video fullscreen, the hotspots are no longer visible or clickable. I tried to inspect element in fullscreen mode and the hotspots would highlight(not visible or clickable) when I dragged my pointer over their <div> but they would be in the wrong position relative to the video. None of this is a problem in windowed mode.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Interactive Video with Responsive Hotspots</title>
        <style>
            /* Responsive container for the video and hotspots */
            #videoContainer {
                position: relative;
                max-width: 100%;
                height: auto;
            }

            /* Video element should maintain aspect ratio */
            #myVideo {
                width: 100%;
                height: auto;
                display: block;
            }

           /* Hotspot styling */
           .hotspot {
                position: absolute;
                background-color: rgba(255, 0, 0, 0.5); /* Semi-transparent red */
                color: white;
                cursor: pointer;
                display: none; /* Hidden by default */
                transition: all 0.2s ease;
            }
        </style>
     </head>
    <body>
        <div id="videoContainer">
            <video id="myVideo" controls>
                <source src="video1.mp4" type="video/mp4">
                Your browser does not support the video tag.
            </video>
            <div id="hotspot1" class="hotspot" onclick="hotspotClick('Hotspot 1')">1</div>
            <div id="hotspot2" class="hotspot" onclick="hotspotClick('Hotspot 2')">2</div>
            <div id="hotspot3" class="hotspot" onclick="hotspotClick('Hotspot 3')">3</div>
            <div id="hotspot4" class="hotspot" onclick="hotspotClick('Hotspot 4')">4</div>
        </div>

        <script>
            const video = document.getElementById('myVideo');
            const hotspot1 = document.getElementById('hotspot1');
            const hotspot2 = document.getElementById('hotspot2');
            const hotspot3 = document.getElementById('hotspot3');
            const hotspot4 = document.getElementById('hotspot4');

            // Define the relative positions (as percentages) and rectangular padding for the hotspots
            const hotspotData = {
                 hotspot1: {
                    showTime: 3, // Show at 3 seconds
                    hideTime: 6, // Hide at 6 seconds
                    positions: { leftPercent: 18, topPercent: 30, widthPercent: 8, heightPercent: 4 }
                },
                 hotspot2: {
                    showTime: 3,
                    hideTime: 6,
                    positions: { leftPercent: 35, topPercent: 30, widthPercent: 8, heightPercent: 4 }
                },
                 hotspot3: {
                    showTime: 3,
                    hideTime: 6,
                    positions: { leftPercent: 52, topPercent: 30, widthPercent: 8, heightPercent: 4 }
                },
                 hotspot4: {
                    showTime: 3,
                    hideTime: 6,
                    positions: { leftPercent: 68, topPercent: 30, widthPercent: 8, heightPercent: 4 }
                }
            };

            // Adjust hotspot position and size based on video and container size, with rectangular          padding
            function adjustHotspotPosition(hotspot, video, positionData) {
                const videoRect = video.getBoundingClientRect();
                const left = (positionData.leftPercent / 100) * videoRect.width;
                const top = (positionData.topPercent / 100) * videoRect.height;
                const width = (positionData.widthPercent / 100) * videoRect.width;
                const height = (positionData.heightPercent / 100) * videoRect.height;

                hotspot.style.left = left + 'px';
                hotspot.style.top = top + 'px';
                hotspot.style.width = width + 'px';
                hotspot.style.height = height + 'px';
                hotspot.style.padding = (height * 0.2) + 'px ' + (width * 0.2) + 'px'; // Rectangular padding
            }

        // Toggle visibility of the hotspot based on video time and update its position
        function toggleHotspot(hotspot, data, currentTime) {
            if (currentTime >= data.showTime && currentTime <= data.hideTime) {
                hotspot.style.display = 'block';
                adjustHotspotPosition(hotspot, video, data.positions);
            } else {
                hotspot.style.display = 'none';
            }
        }

        // Event listener to update hotspots on video time update
        video.addEventListener('timeupdate', function () {
            const currentTime = video.currentTime;

            toggleHotspot(hotspot1, hotspotData.hotspot1, currentTime);
            toggleHotspot(hotspot2, hotspotData.hotspot2, currentTime);
            toggleHotspot(hotspot3, hotspotData.hotspot3, currentTime);
            toggleHotspot(hotspot4, hotspotData.hotspot4, currentTime);
        });

        // Event listener to adjust hotspot positions when the window resizes or video enters fullscreen
        function adjustAllHotspots() {
            adjustHotspotPosition(hotspot1, video, hotspotData.hotspot1.positions);
            adjustHotspotPosition(hotspot2, video, hotspotData.hotspot2.positions);
            adjustHotspotPosition(hotspot3, video, hotspotData.hotspot3.positions);
            adjustHotspotPosition(hotspot4, video, hotspotData.hotspot4.positions);
        }

        // Listen for window resize to reposition hotspots
        window.addEventListener('resize', adjustAllHotspots);

        // Listen for fullscreen change to reposition hotspots for all browsers (Chrome/Brave included)
        function addFullscreenListeners() {
            document.addEventListener('fullscreenchange', adjustAllHotspots);      // Standard
            document.addEventListener('webkitfullscreenchange', adjustAllHotspots); // Safari/Chrome
            document.addEventListener('mozfullscreenchange', adjustAllHotspots);    // Firefox
            document.addEventListener('MSFullscreenChange', adjustAllHotspots);     // IE/Edge
        }

        addFullscreenListeners();

        // Optional: Action on hotspot click
        function hotspotClick(hotspotName) {
            alert(hotspotName + ' clicked!');
        }
    </script>
</body>
</html>

I just need hotspots videos embedded on html5 browsers that maintain their shape, size and position according to the timestamps I want them to appear at. My code works in windowed mode but not in fullscreen mode on any browser

Upvotes: 1

Views: 59

Answers (1)

KLASANGUI
KLASANGUI

Reputation: 1144

When you click on the fullscreen button on a <video> tag, the document itself will remain in windowed state. Only the video content will overlay everything else in fullscreen mode. So, this causes your hotspots to not be displayed (because they're overlayed by the video).

To achieve what you want, you could intercept the fullscreen button which shoud do the following (just a suggestion):

  1. Hide your video.
  2. Create a wrapper that overlays the screen with a higher z-index than overlayed elements.
  3. Create a dynamic image through javascript.
  4. Animate the image to show the current frame of your <video>.
  5. Apply the generated image to the background of your wrapper.
  6. Place your hotspots inside the wrapper at the right time.
  7. Add the video controls at your overlay.

Then, when the user lefts the fullscreen mode:

  1. Unhide your video.
  2. Hide your overlay.

Upvotes: 1

Related Questions