aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/js/plugins/vimeo.js4
-rw-r--r--src/js/plugins/youtube.js4
-rw-r--r--src/js/plyr.js6
-rw-r--r--src/js/utils/style.js57
-rw-r--r--src/sass/types/video.scss10
5 files changed, 66 insertions, 15 deletions
diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js
index ea001441..10246c66 100644
--- a/src/js/plugins/vimeo.js
+++ b/src/js/plugins/vimeo.js
@@ -11,7 +11,7 @@ import fetch from '../utils/fetch';
import is from '../utils/is';
import loadScript from '../utils/load-script';
import { format, stripHTML } from '../utils/strings';
-import { setAspectRatio } from '../utils/style';
+import { roundAspectRatio, setAspectRatio } from '../utils/style';
import { buildUrlParams } from '../utils/urls';
// Parse Vimeo ID from URL
@@ -294,7 +294,7 @@ const vimeo = {
// Set aspect ratio based on video size
Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => {
const [width, height] = dimensions;
- player.embed.ratio = [width, height];
+ player.embed.ratio = roundAspectRatio(width, height);
setAspectRatio.call(this);
});
diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js
index db5781e6..19d2f1a5 100644
--- a/src/js/plugins/youtube.js
+++ b/src/js/plugins/youtube.js
@@ -11,7 +11,7 @@ import loadImage from '../utils/load-image';
import loadScript from '../utils/load-script';
import { extend } from '../utils/objects';
import { format, generateId } from '../utils/strings';
-import { setAspectRatio } from '../utils/style';
+import { roundAspectRatio, setAspectRatio } from '../utils/style';
// Parse YouTube ID from URL
function parseId(url) {
@@ -90,7 +90,7 @@ const youtube = {
ui.setTitle.call(this);
// Set aspect ratio
- this.embed.ratio = [width, height];
+ this.embed.ratio = roundAspectRatio(width, height);
}
setAspectRatio.call(this);
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 6572e473..59381e11 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -29,7 +29,7 @@ import loadSprite from './utils/load-sprite';
import { clamp } from './utils/numbers';
import { cloneDeep, extend } from './utils/objects';
import { silencePromise } from './utils/promise';
-import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateRatio } from './utils/style';
+import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateAspectRatio } from './utils/style';
import { parseUrl } from './utils/urls';
// Private properties
@@ -916,12 +916,12 @@ class Plyr {
return;
}
- if (!is.string(input) || !validateRatio(input)) {
+ if (!is.string(input) || !validateAspectRatio(input)) {
this.debug.error(`Invalid aspect ratio specified (${input})`);
return;
}
- this.config.ratio = input;
+ this.config.ratio = reduceAspectRatio(input);
setAspectRatio.call(this);
}
diff --git a/src/js/utils/style.js b/src/js/utils/style.js
index f02b0ba5..a9659cf4 100644
--- a/src/js/utils/style.js
+++ b/src/js/utils/style.js
@@ -2,9 +2,30 @@
// Style utils
// ==========================================================================
+import { closest } from './arrays';
import is from './is';
-export function validateRatio(input) {
+// Standard/common aspect ratios
+const standardRatios = [
+ [1, 1],
+ [4, 3],
+ [3, 4],
+ [5, 4],
+ [4, 5],
+ [3, 2],
+ [2, 3],
+ [16, 10],
+ [10, 16],
+ [16, 9],
+ [9, 16],
+ [21, 9],
+ [9, 21],
+ [32, 9],
+ [9, 32],
+].reduce((out, [x, y]) => ({ ...out, [x / y]: [x, y] }), {});
+
+// Validate an aspect ratio
+export function validateAspectRatio(input) {
if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {
return false;
}
@@ -14,6 +35,7 @@ export function validateRatio(input) {
return ratio.map(Number).every(is.number);
}
+// Reduce an aspect ratio to it's lowest form
export function reduceAspectRatio(ratio) {
if (!is.array(ratio) || !ratio.every(is.number)) {
return null;
@@ -26,8 +48,9 @@ export function reduceAspectRatio(ratio) {
return [width / divider, height / divider];
}
+// Calculate an aspect ratio
export function getAspectRatio(input) {
- const parse = (ratio) => (validateRatio(ratio) ? ratio.split(':').map(Number) : null);
+ const parse = (ratio) => (validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null);
// Try provided ratio
let ratio = parse(input);
@@ -58,10 +81,20 @@ export function setAspectRatio(input) {
const { wrapper } = this.elements;
const ratio = getAspectRatio.call(this, input);
- const [w, h] = is.array(ratio) ? ratio : [0, 0];
- const padding = (100 / w) * h;
- wrapper.style.paddingBottom = `${padding}%`;
+ if (!is.array(ratio)) {
+ return {};
+ }
+
+ const [x, y] = ratio;
+ const useNative = window.CSS?.supports(`aspect-ratio: ${x} / ${y}`) ?? false;
+ const padding = (100 / x) * y;
+
+ if (useNative) {
+ wrapper.style.aspectRatio = `${x}/${y}`;
+ } else {
+ wrapper.style.paddingBottom = `${padding}%`;
+ }
// For Vimeo we have an extra <div> to hide the standard controls and UI
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
@@ -80,4 +113,18 @@ export function setAspectRatio(input) {
return { padding, ratio };
}
+// Round an aspect ratio to closest standard ratio
+export function roundAspectRatio(x, y, tolerance = 0.05) {
+ const ratio = x / y;
+ const closestRatio = closest(Object.keys(standardRatios), ratio);
+
+ // Check match is within tolerance
+ if (Math.abs(closestRatio - ratio) <= tolerance) {
+ return standardRatios[closestRatio];
+ }
+
+ // No match
+ return [x, y];
+}
+
export default { setAspectRatio };
diff --git a/src/sass/types/video.scss b/src/sass/types/video.scss
index 79b3e158..fe7d8b37 100644
--- a/src/sass/types/video.scss
+++ b/src/sass/types/video.scss
@@ -26,9 +26,13 @@ $embed-padding: ((100 / 16) * 9);
.plyr__video-embed,
.plyr__video-wrapper--fixed-ratio {
- height: 0;
- padding-bottom: to-percentage($embed-padding);
- position: relative;
+ @supports not (aspect-ratio: 16 / 9) {
+ height: 0;
+ padding-bottom: to-percentage($embed-padding);
+ position: relative;
+ }
+
+ aspect-ratio: 16 / 9;
}
.plyr__video-embed iframe,