1
0
mirror of https://github.com/videojs/video.js.git synced 2025-02-02 11:34:50 +02:00

feat: Use picture el for poster (#7865)

BREAKING CHANGE: This changes the DOM structure used for the video poster.
This commit is contained in:
mister-ben 2022-08-22 18:15:02 +02:00 committed by Pat O'Neill
parent b0101a6b9b
commit f2aa0d7d13
4 changed files with 83 additions and 25 deletions

View File

@ -1,10 +1,6 @@
.vjs-poster {
display: inline-block;
vertical-align: middle;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
background-color: #000000;
cursor: pointer;
margin: 0;
padding: 0;

View File

@ -820,25 +820,29 @@ class Player extends Component {
*
* @see [Video Element Attributes]{@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-crossorigin}
*
* @param {string} [value]
* @param {string|null} [value]
* The value to set the `Player`'s crossOrigin to. If an argument is
* given, must be one of `anonymous` or `use-credentials`.
* given, must be one of `'anonymous'` or `'use-credentials'`, or 'null'.
*
* @return {string|undefined}
* @return {string|null|undefined}
* - The current crossOrigin value of the `Player` when getting.
* - undefined when setting
*/
crossOrigin(value) {
if (!value) {
// `null` can be set to unset a value
if (typeof value === 'undefined') {
return this.techGet_('crossOrigin');
}
if (value !== 'anonymous' && value !== 'use-credentials') {
log.warn(`crossOrigin must be "anonymous" or "use-credentials", given "${value}"`);
if (value !== null && value !== 'anonymous' && value !== 'use-credentials') {
log.warn(`crossOrigin must be null, "anonymous" or "use-credentials", given "${value}"`);
return;
}
this.techCall_('setCrossOrigin', value);
if (this.posterImage) {
this.posterImage.crossOrigin(value);
}
return;
}

View File

@ -46,16 +46,56 @@ class PosterImage extends ClickableComponent {
* The element that gets created.
*/
createEl() {
const el = Dom.createEl('div', {
const el = Dom.createEl('picture', {
className: 'vjs-poster',
// Don't want poster to be tabbable.
tabIndex: -1
});
}, {}, Dom.createEl('img', {
loading: 'lazy',
crossOrigin: this.crossOrigin()
}));
return el;
}
/**
* Get or set the `PosterImage`'s crossOrigin option.
*
* @param {string|null} [value]
* The value to set the crossOrigin to. If an argument is
* given, must be one of `'anonymous'` or `'use-credentials'`, or 'null'.
*
* @return {string|null}
* - The current crossOrigin value of the `Player` when getting.
* - undefined when setting
*/
crossOrigin(value) {
// `null` can be set to unset a value
if (typeof value === 'undefined') {
if (this.el_) {
// If the poster's element exists, give its value
return this.el_.querySelector('img').crossOrigin;
} else if (this.player_.tech_ && this.player_.tech_.isReady_) {
// If not but the tech is ready, query the tech
return this.player_.crossOrigin();
}
// Otherwise check options as the poster is usually set before the state of crossorigin
// can be retrieved by the getter
return this.player_.options_.crossOrigin || this.player_.options_.crossorigin || null;
}
if (value !== null && value !== 'anonymous' && value !== 'use-credentials') {
this.player_.log.warn(`crossOrigin must be null, "anonymous" or "use-credentials", given "${value}"`);
return;
}
this.el_.querySelector('img').crossOrigin = value;
return;
}
/**
* An {@link EventTarget~EventListener} for {@link Player#posterchange} events.
*
@ -85,15 +125,7 @@ class PosterImage extends ClickableComponent {
* The URL to the source for the `PosterImage`.
*/
setSrc(url) {
let backgroundImage = '';
// Any falsy value should stay as an empty string, otherwise
// this will throw an extra error
if (url) {
backgroundImage = `url("${url}")`;
}
this.el_.style.backgroundImage = backgroundImage;
this.el_.querySelector('img').src = url;
}
/**
@ -126,5 +158,20 @@ class PosterImage extends ClickableComponent {
}
/**
* Get or set the `PosterImage`'s crossorigin option. For the HTML5 player, this
* sets the `crossOrigin` property on the `<img>` tag to control the CORS
* behavior.
*
* @param {string|null} [value]
* The value to set the `PosterImages`'s crossorigin to. If an argument is
* given, must be one of `anonymous` or `use-credentials`.
*
* @return {string|null|undefined}
* - The current crossorigin value of the `Player` when getting.
* - undefined when setting
*/
PosterImage.prototype.crossorigin = PosterImage.prototype.crossOrigin;
Component.registerComponent('PosterImage', PosterImage);
export default PosterImage;

View File

@ -18,19 +18,30 @@ QUnit.module('PosterImage', {
QUnit.test('should create and update a poster image', function(assert) {
const posterImage = new PosterImage(this.mockPlayer);
let backgroundImage = posterImage.el().style.backgroundImage;
let pictureImg = posterImage.$('img').src;
assert.notEqual(backgroundImage.indexOf(this.poster1), -1, 'Background image used');
assert.notEqual(pictureImg.indexOf(this.poster1), -1, 'Background image used');
// Update with a new poster source and check the new value
this.mockPlayer.poster_ = this.poster2;
this.mockPlayer.trigger('posterchange');
backgroundImage = posterImage.el().style.backgroundImage;
assert.notEqual(backgroundImage.indexOf(this.poster2), -1, 'Background image updated');
pictureImg = posterImage.$('img').src;
assert.notEqual(pictureImg.indexOf(this.poster2), -1, 'Background image updated');
posterImage.dispose();
});
QUnit.test('should mirror crossOrigin', function(assert) {
assert.strictEqual(this.mockPlayer.posterImage.$('img').crossOrigin, null, 'crossOrigin not set when not present in options');
assert.strictEqual(this.mockPlayer.posterImage.crossOrigin(), null, 'crossOrigin not set from getter when not present in options');
this.mockPlayer.crossOrigin('anonymous');
assert.strictEqual(this.mockPlayer.posterImage.$('img').crossOrigin, 'anonymous', 'crossOrigin updated');
assert.strictEqual(this.mockPlayer.posterImage.crossOrigin(), 'anonymous', 'crossOrigin getter returns updated value');
});
QUnit.test('should remove itself from the document flow when there is no poster', function(assert) {
const posterImage = new PosterImage(this.mockPlayer);