Click event not triggering over youtube iframe in

2019-03-12 17:17发布

问题:

I’d like to place interaction controls above a youtube iframe video, and I got it working quite OK by just adding wmode=opaque as arguments and then position the elements absolute above the iframe.

My problem is that on mobile safari - the controls work fine first, but when I return from the fullscreen video, they are all disabled. It works fine on desktop though.

The HTML is basically:

<iframe src="http://www.youtube.com/embed/[ID]?wmode=opaque"></iframe>
<button id="btn">Click me</button>

And then the button is positioned absolute above the iframe.

For a demo, please visit this fiddle using your mobile safari: http://jsfiddle.net/SwGH5/embedded/result/

You’ll see that the button yields an alert when clicked. Now, play the video and click "done". Then try to click the button again...

If the movie was embedded using the <video> tag I could listen for a fullscreen-end event and do something, but now I’m stuck...

Here’s the fiddle: http://jsfiddle.net/SwGH5

回答1:

So I played around with the iframe API a bit and found a solution. It's kind of hacky... but not really. When a user clicks on the video to play it, the document.activeElement becomes the iframe. When the user clicks the "done" button, the document.activeElement === document.body. So when the video starts playing, we periodically check to see if the active element returns to the body. At that point, the only solution I found was to redraw the iframe. In the example, I destroy() the video and recreate it using the iframe API. I also tried cloning the iframe and replacing it with success (I left that code there so you could see it):

http://jsfiddle.net/ryanwheale/SwGH5/105/

It's not the best solution, but it works. Also, to give an explanation of what [I think] is happening - iOS hijacks any video content (Safari or Chrome) and plays it using the native video player. Any type of OS functionality like this takes place "over" the browser if you will - higher than any z-index... completely outside the browser. When the user clicks "done" the native player kind of zooms out as if it is re-implanting itself on the page. My best guess is that the native player is still hanging out "over" the browser... thus making anything underneath it inaccessible. The fact that the button appears to be on top is just an anomaly... for lack of better description.



回答2:

EDIT: Ryan Wheale's solution is a better workaround to this problem and will work in most cases.

From Apple’s documentation:

On iOS-based devices with small screens—such as iPhone and iPod touch—video always plays in fullscreen mode, so the canvas cannot be superimposed on playing video. On iOS-based devices with larger screens, such as iPad, you can superimpose canvas graphics on playing video, just as you can on the desktop.

Same goes for a "played video" either. This article clearly states it's not possible.

Workaround:

You could detach and re-attach the iframe element on webkitfullscreenchange. But it won't work for a foreign iframe. Browser will not allow you to manipulate iframe DOM bec. of the cross-domain policy. And even if it did, you could only hide the video overlay to reach your button anyway.

So, the only solution is watching for YT.PlayerState.ENDED state via YouTube iFrame API and then destroying and re-creating the player. But don't worry it plays smooth.

window.onYouTubeIframeAPIReady = function () {
    var video = {
        player: null,
        create: function () {
            // first destroy if we already have the player
            if (video.player) { video.player.destroy(); }
            // create the player
            video.player = new YT.Player('ytp', {
                videoId: '9u_hp7zPir0',
                width: '620',
                height: '290',
                events: {
                    'onStateChange': video.onStateChange
                }
            });
        },
        onStateChange: function (event) {
            // YT.PlayerState.ENDED » exiting full screen
            if (event.data === 0) { video.create(); }
        }
    };
    video.create();
};

Here is the working fiddle.



回答3:

If you can't get it to work with the regular iframe, you might want to consider using mediaelement.js - which can wrap the Youtube API in a HTML5 Media API wrapper. That works fine on safari on ios - try the Youtube example at mediaelementjs.com.

All you need to do is to add the mejs js/css and put your youtube video as source in your video tag, here is some example markup taken from mediaelementjs.com:

<script src="jquery.js"></script>
<script src="mediaelement-and-player.min.js"></script>
<link rel="stylesheet" href="mediaelementplayer.css" />
<video width="640" height="360" id="player1" preload="none">
    <source type="video/youtube" src="http://www.youtube.com/watch?v=nOEw9iiopwI" />
</video>

Then start the player like so:

jQuery(document).ready(function($) {
    $('#player1').mediaelementplayer();
});

If you want to add your button ontop of the mejs player it will work fine, just set the z-index high enough. If you want a regular play button you could also consider styling the existing one that comes with mejs.



回答4:

By the comments from @CullenJ's answer, possibly it might be due to some problem in iOS device browsers not triggering the click event on iframe elements. In that case, you would have to change from:

document.getElementById('btn').onclick = function() {
    alert('clicked');
}

To something like this (as answered by @smnh):

$('#btn').on('click tap touchstart', function() {
    alert('clicked');
});