M src/js/listeners.js => src/js/listeners.js +41 -45
@@ 10,7 10,7 @@ import { getElement, getElements, matches, toggleClass } from './utils/elements'
import { off, on, once, toggleListener, triggerEvent } from './utils/events';
import is from './utils/is';
import { silencePromise } from './utils/promise';
-import { getAspectRatio, setAspectRatio } from './utils/style';
+import { getAspectRatio, getViewportSize, supportsCSS } from './utils/style';
class Listeners {
constructor(player) {
@@ 149,16 149,16 @@ class Listeners {
break;
/* case 73:
- this.setLoop('start');
- break;
+ this.setLoop('start');
+ break;
- case 76:
- this.setLoop();
- break;
+ case 76:
+ this.setLoop();
+ break;
- case 79:
- this.setLoop('end');
- break; */
+ case 79:
+ this.setLoop('end');
+ break; */
default:
break;
@@ 305,39 305,49 @@ class Listeners {
);
// Set a gutter for Vimeo
- const setGutter = (ratio, padding, toggle) => {
+ const setGutter = () => {
if (!player.isVimeo || player.config.vimeo.premium) {
return;
}
- const target = player.elements.wrapper.firstChild;
- const [, y] = ratio;
- const [videoX, videoY] = getAspectRatio.call(player);
-
- target.style.maxWidth = toggle ? `${(y / videoY) * videoX}px` : null;
- target.style.margin = toggle ? '0 auto' : null;
- };
+ const target = elements.wrapper;
+ const { active } = player.fullscreen;
+ const [videoWidth, videoHeight] = getAspectRatio.call(player);
+ const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`);
- // Resize on fullscreen change
- const setPlayerSize = (measure) => {
- // If we don't need to measure the viewport
- if (!measure) {
- return setAspectRatio.call(player);
+ // If not active, remove styles
+ if (!active) {
+ if (useNativeAspectRatio) {
+ target.style.width = null;
+ target.style.height = null;
+ } else {
+ target.style.maxWidth = null;
+ target.style.margin = null;
+ }
+ return;
}
- const rect = elements.container.getBoundingClientRect();
- const { width, height } = rect;
+ // Determine which dimension will overflow and constrain view
+ const [viewportWidth, viewportHeight] = getViewportSize();
+ const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;
- return setAspectRatio.call(player, `${width}:${height}`);
+ if (useNativeAspectRatio) {
+ target.style.width = overflow ? 'auto' : '100%';
+ target.style.height = overflow ? '100%' : 'auto';
+ } else {
+ target.style.maxWidth = overflow ? `${(viewportHeight / videoHeight) * videoWidth}px` : null;
+ target.style.margin = overflow ? '0 auto' : null;
+ }
};
+ // Handle resizing
const resized = () => {
clearTimeout(timers.resized);
- timers.resized = setTimeout(setPlayerSize, 50);
+ timers.resized = setTimeout(setGutter, 50);
};
on.call(player, elements.container, 'enterfullscreen exitfullscreen', (event) => {
- const { target, usingNative } = player.fullscreen;
+ const { target } = player.fullscreen;
// Ignore events not from target
if (target !== elements.container) {
@@ 349,26 359,12 @@ class Listeners {
return;
}
- const isEnter = event.type === 'enterfullscreen';
- // Set the player size when entering fullscreen to viewport size
- const { padding, ratio } = setPlayerSize(isEnter);
-
// Set Vimeo gutter
- setGutter(ratio, padding, isEnter);
-
- // Horrible hack for Safari 14 not repainting properly on entering fullscreen
- if (isEnter) {
- setTimeout(() => repaint(elements.container), 100);
- }
+ setGutter();
- // If not using native browser fullscreen API, we need to check for resizes of viewport
- if (!usingNative) {
- if (isEnter) {
- on.call(player, window, 'resize', resized);
- } else {
- off.call(player, window, 'resize', resized);
- }
- }
+ // Watch for resizes
+ const method = event.type === 'enterfullscreen' ? on : off;
+ method.call(player, window, 'resize', resized);
});
};
M src/js/utils/style.js => src/js/utils/style.js +21 -6
@@ 5,6 5,15 @@
import { closest } from './arrays';
import is from './is';
+// Check support for a CSS declaration
+export function supportsCSS(declaration) {
+ if (!window || !window.CSS) {
+ return false;
+ }
+
+ return window.CSS.supports(declaration);
+}
+
// Standard/common aspect ratios
const standardRatios = [
[1, 1],
@@ 67,10 76,10 @@ export function getAspectRatio(input) {
// Get from HTML5 video
if (ratio === null && this.isHTML5) {
const { videoWidth, videoHeight } = this.media;
- ratio = reduceAspectRatio([videoWidth, videoHeight]);
+ ratio = [videoWidth, videoHeight];
}
- return ratio;
+ return reduceAspectRatio(ratio);
}
// Set aspect ratio for responsive container
@@ 86,8 95,8 @@ export function setAspectRatio(input) {
return {};
}
- const [x, y] = ratio;
- const useNative = window.CSS ? window.CSS.supports(`aspect-ratio: ${x}/${y}`) : false;
+ const [x, y] = reduceAspectRatio(ratio);
+ const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);
const padding = (100 / x) * y;
if (useNative) {
@@ 107,7 116,7 @@ export function setAspectRatio(input) {
this.media.style.transform = `translateY(-${offset}%)`;
}
} else if (this.isHTML5) {
- wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
+ wrapper.classList.add(this.config.classNames.videoFixedRatio);
}
return { padding, ratio };
@@ 127,4 136,10 @@ export function roundAspectRatio(x, y, tolerance = 0.05) {
return [x, y];
}
-export default { setAspectRatio };
+// Get the size of the viewport
+// https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions
+export function getViewportSize() {
+ const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
+ const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
+ return [width, height];
+}
M src/sass/lib/mixins.scss => src/sass/lib/mixins.scss +0 -11
@@ 59,17 59,6 @@
height: 100%;
}
- .plyr__video-wrapper {
- height: 100%;
- position: static;
- }
-
- // Vimeo requires some different styling
- &.plyr--vimeo .plyr__video-wrapper {
- height: 0;
- position: relative;
- }
-
// Display correct icon
.plyr__control .icon--exit-fullscreen {
display: block;
M src/sass/types/video.scss => src/sass/types/video.scss +5 -10
@@ 14,7 14,6 @@
.plyr__video-wrapper {
background: var(--plyr-video-background, $plyr-video-background);
- height: 100%;
margin: auto;
overflow: hidden;
position: relative;
@@ 45,17 44,13 @@ $embed-padding: ((100 / 16) * 9);
width: 100%;
}
-// If the full custom UI is supported
-.plyr--full-ui .plyr__video-embed {
+// For Vimeo, if the full custom UI is supported
+.plyr--full-ui .plyr__video-embed > .plyr__video-embed__container {
$height: 240;
$offset: to-percentage(($height - $embed-padding) / ($height / 50));
-
- // Only used for Vimeo
- > .plyr__video-embed__container {
- padding-bottom: to-percentage($height);
- position: relative;
- transform: translateY(-$offset);
- }
+ padding-bottom: to-percentage($height);
+ position: relative;
+ transform: translateY(-$offset);
}
// Controls container