feat: custom controls option for embedded players

This commit is contained in:
Sam Potts 2020-10-19 22:26:33 +11:00
parent fa653a8859
commit 776b0c4036
4 changed files with 62 additions and 46 deletions

View File

@ -59,9 +59,11 @@ import toggleClass from './toggle-class';
},
previewThumbnails: {
enabled: true,
customControls: true,
src: ['https://cdn.plyr.io/static/demo/thumbs/100p.vtt', 'https://cdn.plyr.io/static/demo/thumbs/240p.vtt'],
},
vimeo: {
customControls: true,
// Prevent Vimeo blocking plyr.io demo site
referrerPolicy: 'no-referrer',
},

View File

@ -422,20 +422,23 @@ const defaults = {
title: false,
speed: true,
transparent: false,
// Custom settings from Plyr
customControls: false,
referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc)
premium: false,
// Custom settings from Plyr
referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
},
// YouTube plugin
youtube: {
noCookie: false, // Whether to use an alternative version of YouTube without cookies
rel: 0, // No related vids
showinfo: 0, // Hide info
iv_load_policy: 3, // Hide annotations
modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: false,
noCookie: false, // Whether to use an alternative version of YouTube without cookies
},
};

View File

@ -112,17 +112,20 @@ const vimeo = {
}
// Inject the package
const { poster } = player;
if (premium) {
iframe.setAttribute('data-poster', poster);
if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
player.media = replaceElement(iframe, player.media);
} else {
const wrapper = createElement('div', { class: player.config.classNames.embedContainer, 'data-poster': poster });
const wrapper = createElement('div', {
class: player.config.classNames.embedContainer,
'data-poster': player.poster,
});
wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media);
}
// Get poster image
if (!config.customControls) {
fetch(format(player.config.urls.vimeo.api, id), 'json').then((response) => {
if (is.empty(response)) {
return;
@ -137,6 +140,7 @@ const vimeo = {
// Set and show poster
ui.setPoster.call(player, url.href).catch(() => {});
});
}
// Setup instance
// https://github.com/vimeo/player.js
@ -407,7 +411,9 @@ const vimeo = {
});
// Rebuild UI
if (config.customControls) {
setTimeout(() => ui.build.call(player), 0);
}
},
};

View File

@ -104,6 +104,7 @@ const youtube = {
// API ready
ready() {
const player = this;
const config = player.config.youtube;
// Ignore already setup (race condition)
const currentId = player.media && player.media.getAttribute('id');
if (!is.empty(currentId) && currentId.startsWith('youtube-')) {
@ -121,13 +122,11 @@ const youtube = {
// Replace the <iframe> with a <div> due to YouTube API issues
const videoId = parseId(source);
const id = generateId(player.provider);
// Get poster, if already set
const { poster } = player;
// Replace media element
const container = createElement('div', { id, 'data-poster': poster });
const container = createElement('div', { id, 'data-poster': config.customControls ? player.poster : undefined });
player.media = replaceElement(container, player.media);
// Id to poster wrapper
if (config.customControls) {
const posterSrc = (s) => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;
// Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
@ -142,8 +141,7 @@ const youtube = {
}
})
.catch(() => {});
const config = player.config.youtube;
}
// Setup instance
// https://developers.google.com/youtube/iframe_api_reference
@ -153,11 +151,16 @@ const youtube = {
playerVars: extend(
{},
{
autoplay: player.config.autoplay ? 1 : 0, // Autoplay
hl: player.config.hl, // iframe interface language
controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported
disablekb: 1, // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback
// Autoplay
autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language
hl: player.config.hl,
// Only show controls if not fully supported or opted out
controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it
disablekb: 1,
// Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language,
@ -302,7 +305,7 @@ const youtube = {
player.options.speed = speeds.filter((s) => player.config.speed.options.includes(s));
// Set the tabindex to avoid focus entering iframe
if (player.supported.ui) {
if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1);
}
@ -335,7 +338,9 @@ const youtube = {
}, 200);
// Rebuild UI
if (config.customControls) {
setTimeout(() => ui.build.call(player), 50);
}
},
onStateChange(event) {
// Get the instance
@ -386,7 +391,7 @@ const youtube = {
case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause();
} else {
assurePlaybackState.call(player, true);