'How to show overlay on Plyr (html5 video player) when in Fullscreen?

I have an application that plays SVG overlayed an HTMl5 vido tag (using Plyr HTML5 player). This works great until the user clicks the "Enter Fullscreen" option. This worked when using a previous defunct player. I would get notification and adjust my overlay accordingly, but this just does not work with Plyr.

I think what is happening is Plyr is uing the browsers (specifically chrome) Fullscreen API to do some of this work, which precludes anything else being fullscreen and on top (via z-index, etc).

I'd like to figure out how to do my overlays in fullscreen mode. This could involve: 1) something I have missed or misunderstood with Plyr, or 2) force Plyr into fallback mode (any ideas how to do this?)

Looking for some good suggestions on how to accomplish this.



Solution 1:[1]

Ok, took a bit, then I forgot about this questions, so I'll answer it with what I did.

let plyrVideoWrapper = document.getElementsByClassName('plyr__video_wrapper')
if (plyrVideoWrapper) {
    let myPluginCollection = document.getElementsByClassName('svg-embedded')
    if (myPluginCollection) {
        plyrVideoWrapper[0].appendChild(myPluginCollection[0])
    }
}

This basically moves my overlay plug-in, into the plyr area that has the <video> tag. I use the following CSS for my 'svg-embedded':

.svg-embedded {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: hidden;
}

It all works as expected.

Solution 2:[2]

If you're using Plyr with React, here how you implement the @Hawkeye64 solution.

  • Implement your Overlay component and put together with your video component render:
    <Overlay />
    <video ref={innerRef} className="plyr" .../> 
  • Use useEffect to check when the innerRef is rendered and ready, and move your Overlay component to the Plyr's video wrapper:

    useEffect(() => {
      if (innerRef.current) {
        const wrapper = document.getElementsByClassName("plyr__video-wrapper");
        if (wrapper) {
          const overlay = document.getElementById("my_overlay_id");
          wrapper[0].appendChild(overlay);
        }
      }
    }, [innerRef]);

Make sure to implement an id in your Overlay component, so you can retrieve using the getElementById, replace the my_overlay_id by yours in the code above.

If you want to overlay the all video area, use the CSS below as an starting point:


    .overlay {
      background-color: rgba(56, 3, 3, 0.66);
      height: 100%;
      width: 100%;
      left: 0;
      top: 0;
      position: absolute;
      z-index: 4;
    }

Solution 3:[3]

Better and more correct solution if you're using React is using react-portal like so:


import { Portal } from 'react-portal';

...

<Portal node={(document && document.getElementsByClassName('plyr__controls')[0])}>
 Your overlay here...
</Portal>

if you want your overlay to be part of controls, Or if you want to be always visible:

<Portal node={(document && document.getElementsByClassName('plyr__video-wrapper')[0])}>
 Your overlay here...
</Portal>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Paulo Oliveira
Solution 3 Mark Sergienko