问题
Is it possible to trigger an action on click if a video is set to background=1 (no controls)?
This is a Vimeo video, plus account (where background=1 is permitted).
Essentially, I have a Vimeo video with no controls set to loop and autoplay with a volume of 0. My implementation has an icon overlayed on top of the video, in the center. When clicked, it is set to full volume and the icon is hidden.
Once the volume is set to 1 and the icon is hidden, the person viewing should have the option of clicking the video so as to mute it (set volume to 0).
The problem is that I am not able to figure out how to target this click. I have tried attaching an .on('click') to the iframe, its parent, and as far up the chain as I can go but beyond that first click of the icon, the click is never registered.
Can anyone please offer any pointers on how to target a click on a Vimeo iframe video (or its parent container, etc)?
Here is my code thus far:
var iframe = document.getElementById('vimeo-video');
var player = new Vimeo.Player(iframe);
player.ready().then(function() {
var volume = 0
player.setVolume(volume);
$('#vimeo-video-play').on('click', function(event) {
if (volume > 0) {
player.setVolume(0);
} else {
player.setVolume(1);
}
$('#vimeo-video-play').hide();
});
});
回答1:
Vimeo Promises
It appears that if you use Vimeo API, you must return a Promise. If you just want to do a simple task such as controlling the volume, the documentation gives this example:
player.setVolume(0.5).then(function(volume) { // volume was set }).catch(function(error) { switch (error.name) { case 'RangeError': // the volume was less than 0 or greater than 1 break; default: // some other error occurred break; } });
Not simple, and it's overkill. It's not apparent by looking at it but if you see then()
, await
async
, new Promise
you can say with 99.9% certainty that a Promise will be returned. I haven't looked deep enough into player.js but I think each method is wrapped in a Promise so as far as I could tell, we can just return the method without using all of that extra crap. So compare the above code to the following:
var sVol = player.setVolume(1); return sVol;
So I believe when invoking a Vimeo API method, we can return the function as a value. There's no work involving what exactly that value is because it's going to be either resolved or rejected. A Promise is also immutable so returning the function itself should be a guaranteed resolve (concerning Vimeo methods, not Promises in general).
Overlay Layout
Instead of clicking an iframe which is filled with a video player that will do 100 other tasks except your custom callback, you need to click an element outside of the iframe. As a background video without controls, you are very limited. I suggest an element that covers the iframe player edge to edge so that the user clicks it and nothing else. The following are the steps to setup an overlay:
Wrap the iframe player (
#vFrame0
in the demo) in a relpos🞳 parent container (a.k.a..box
)Place an older sibling🗡 abspos🞳 element (a.k.a.
.overlay
) inside the parent with the iframe player.Set the older sibling "above" the player by setting its
z-index
at l more than the iframe player and the necessary CSS properties (see demo CSS for.overlay
) to ensure that the older sibling covers the iframe player edge to edge completely.Register the click event to the overlay element so when the player ignores the click event, the event will bubble back to the older sibling overlay element. The overlay element is now a proxy of sorts and will run the callback:
var sVol = player.setVolume(1); return sVol
Demo
This Demo does not function because there are conflicts between Vimeo's connections and SO's security measures. For a functioning Demo review this Plunker or this Plunker.
<!DOCTYPE html>
<html>
<head>
<base href="https://player.vimeo.com/api/demo">
<meta charset='utf-8'>
<style>
.box {
display: table;
border: 3px dashed red;
position: relative;
}
.overlay {
cursor: pointer;
display: table-cell;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-height: 100%;
z-index: 1;
}
.overlay::before {
position: absolute;
cursor: pointer;
display: block;
content: '🕪';
font-size: 2em;
width: 2em;
height: 2em;
color: cyan;
opacity: 0;
transition: opacity .5s ease 3s;
}
.overlay:hover::before {
opacity: 1;
transition: .5s ease;
}
.mute.overlay::before {
content: '🕩';
}
</style>
</head>
<body>
<figure class='box'>
<figcaption class='overlay mute'></figcaption>
<div id='vFrame0' data-vimeo-id="76979871" data-vimeo-autoplay data-vimeo-background></div>
</figure>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src='https://player.vimeo.com/api/player.js'></script>
<script>
var player = new Vimeo.Player('vFrame0', options);
var options = {
mute: true
};
$('.overlay').on('click', function(e) {
var state = $(this).hasClass('mute') ? player.setVolume(1) : player.setVolume(0);
$(this).toggleClass('mute');
return state;
});
</script>
</body>
</html>
🞳relpos: position: relative
| abspos position: absolute
🗡older sibling an element that is positioned before the element being referred to.
来源:https://stackoverflow.com/questions/51053115/possible-to-trigger-on-vimeo-video-click