Search code examples
javascriptcssvideo.js

How to show HTML video overlays with VideoJS in fullscreen?


I have a quiz video overlay that shows up nicely when the videojs player is in standard mode: https://jsfiddle.net/c4nxdf38/

However, when entering fullscreen it disappears (probably behind the video).

I found an obsolete solution which specifies the z-index of the overlay to the maximum. It is not working in the latest Chrome and Firefox.

I found another solution to do the fullscreen with the parent, not the videoplayer itself, but it's not working with the videojs player setup.

Then I found a promising solution how to make overlay elements appear on fullscreen by setting position:absolute; and tried to implement it without success: https://jsfiddle.net/5Lqfyzh4/

HTML from my last attempt (see fiddle):

<div id="main-container">

<div id="overlays-wrap">

    <div class="overlay-item" data-overlayid="59" data-time="41">
    <p class="vo-question">
        Welche Zahl ist die Summe bei 3 + 50 = 53?
    </p>

    <div class="vtask-choices-wrap">

        <div class="vtask-choice-item">
        <input class="vtask-choice" type="radio" name="quiz" id="59-a1" value="1" data-correct="0">
        <label class="radio-tile" for="59-a1">
            <span class="radio-tile-label">
            3
            </span>
        </label>
        </div>

        <div class="vtask-choice-item">
        <input class="vtask-choice" type="radio" name="quiz" id="59-a2" data-correct="0">
        <label class="radio-tile" for="59-a2">
            <span class="radio-tile-label">
            50
            </span>
        </label>
        </div>

        <div class="vtask-choice-item">
        <input class="vtask-choice" type="radio" name="quiz" id="59-a3" value="3" data-correct="1"> 
        <label class="radio-tile" for="59-a3">
            <span class="radio-tile-label">
            53
            </span>
        </label>
        </div>


    </div> <!-- vtask-choices-wrap -->

    <a class="buttonb vtask-btn-continue">Continue</a>

    </div> <!-- overlay-item -->

</div>


<div id="videowrapper">
    <video id="videoplay" class="video-js vjs-default-skin" controls preload="metadata" width="854" height="480" poster="" autoplay="true">
    <source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4"> 
    </video>
</div>


</div>

Javascript:

$(document).ready(function() {

var options = {
    playbackRates: [1, 1.5, 2],
    muted: true,
};

video = videojs('videoplay', options);

video.ready(function() {
    /*
       this.on('fullscreenchange',function() {
          console.log('fullscreen event');
       });
    */
}); // end video.ready 


// OVERLAY PREPARE
// $('#overlays-wrap, .overlay-item').hide();

// OVERLAY INTERACTION
$('.radio-tile').click( function() {
    // only show if not yet submitted, prevents submit then click again on radio-tile which would show the vtask-btn-continue
    var submitted = $(this).closest('.overlay-item').hasClass('overlay-submitted');
    if(!submitted)
    {
    $(this).parent().parent().next('.vtask-btn-continue').css('visibility', 'visible');
    // make sure we check the radio button 
    $(this).prev('.vtask-choice').prop('checked', true);
    }
});

$('.vtask-btn-continue').click( function() {
    // hide continue button
    $(this).css('visibility', 'hidden');

    var overlay = $(this).closest('.overlay-item'); // $(this).parent()
    overlay.hide();

});

}); // END ready

CSS:

#overlays-wrap {
position: absolute;
width: 100%;
height: 100%;
max-height:460px;
left: 0;
top: 0;
z-index: 2147483647;
}

.overlay-item {
position: absolute;
top: 0;
color: #FFF;
font-size: 20px;
background-color: rgba(0, 0, 0, 0.85);
width: 100%;
height: 100%;
padding: 0;
z-index: 2147483647;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
backface-visibility: hidden;
}

.overlay-item .vo-question {
margin: 10px 0 40px 0;
width: 80%;
text-align: center;
line-height: 1.5;
}

.vtask-choices-wrap {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-evenly;
width: 100%;
max-width: 1000px;
min-height: 10rem;
}

.vtask-choice-item .vtask-choice {
opacity: 0;
position: absolute;
top: 0;
left: 0;
}

.radio-tile {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 2px solid #079ad9;
border-radius: 5px;
padding: 1rem;
transition: transform 300ms ease;
background: rgba(0,0,0,0.5);
z-index: 500;
cursor: pointer;
font-size: 18px;
text-align: center;
}

.vtask-btn-continue {
color: #FFFFFF!important;
border-color: #2B78C5;
border-bottom-color: #2a65a0;
text-decoration: none;
text-shadow: none;
color: #FFF;
background: #39F;
margin-top: 40px;
padding: 10px 20px;
font-family: Arial,sans-serif;
font-size: 16px;
}


/* FIX according https://stackoverflow.com/a/13388579/1066234 */
#videoplay {
position: absolute;
left: 0px;
top: 0px;
min-height: 100%;
min-width: 100%;
z-index: 9997;
}
#overlays-wrap {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
z-index: 9998;
}

#main_container {
float: left;
position: relative;
left:0;
top:0;
}

Interestingly, with the videojs plugin at https://github.com/brightcove/videojs-overlay the fullscreen overlays seem to work even on fullscreen. But I cannot figure out how it is doing it. – Demo: http://www.xfaktor.com/overlay/overlay_kroger.html – I have more complex HTML for my overlays and cannot use this plugin.

What is the solution for this video/videojs problem?

Probably it would be best if you can help, having the starting point of this fiddle (my recent implementation): https://jsfiddle.net/w5f7mk19/ Thanks!


Solution

  • The problem appears to be, that this library wraps the video in an additional div, and makes that div fullscreen - but your #overlays-wrap element is outside of that element, and I don’t think z-index is supposed to change anything about that(?).

    Putting the overlay directly into #videowrapper in the source code doesn’t do the trick - the player library takes #videoplay, creates the wrapper div and puts the id on that. (It changes the id of the video element itself to #videoplay_html5_api, so no conflict in that regard.) The new div #videoplay becomes fullscreen, but #overlays-wrap still only is a sibling in the DOM, so outside of the fullscreen element.

    But if you move #overlays-wrap into #videoplay after the player has initialized, it seems to work:

    video = videojs('videoplay', options); // wraps video element into div#videoplay
    
    $('#overlays-wrap').appendTo($('#videoplay')); // append #overlays-wrap to div#videoplay
    

    https://jsfiddle.net/pw89cjqe/