Skip to content

Commit

Permalink
feat: text track display overlays a video (#8009)
Browse files Browse the repository at this point in the history
  • Loading branch information
gjanblaszczyk authored Apr 11, 2023
1 parent d26780e commit 1491d71
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
56 changes: 53 additions & 3 deletions src/js/tracks/text-track-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ function tryUpdateStyle(el, style, rule) {
}
}

/**
* Converts the CSS top/right/bottom/left property numeric value to string in pixels.
*
* @param {number} position
* The CSS top/right/bottom/left property value.
*
* @return {string}
* The CSS property value that was created, like '10px'.
*
* @private
*/
function getCSSPositionValue(position) {
return position ? `${position}px` : '';
}

/**
* The component for displaying text track cues.
*
Expand All @@ -99,11 +114,18 @@ class TextTrackDisplay extends Component {
constructor(player, options, ready) {
super(player, options, ready);

const updateDisplayHandler = (e) => this.updateDisplay(e);
const updateDisplayTextHandler = (e) => this.updateDisplay(e);
const updateDisplayHandler = (e) => {
this.updateDisplayOverlay();
this.updateDisplay(e);
};

player.on('loadstart', (e) => this.toggleDisplay(e));
player.on('texttrackchange', updateDisplayHandler);
player.on('loadedmetadata', (e) => this.preselectTrack(e));
player.on('texttrackchange', updateDisplayTextHandler);
player.on('loadedmetadata', (e) => {
this.updateDisplayOverlay();
this.preselectTrack(e);
});

// This used to be called during player init, but was causing an error
// if a track should show by default and the display hadn't loaded yet.
Expand Down Expand Up @@ -297,6 +319,34 @@ class TextTrackDisplay extends Component {
}
}

/**
* Updates the displayed TextTrack to be sure it overlays the video when a either
* a {@link Player#texttrackchange} or a {@link Player#fullscreenchange} is fired.
*/
updateDisplayOverlay() {
if (!this.player_.videoHeight()) {
return;
}

const playerWidth = this.player_.currentWidth();
const playerHeight = this.player_.currentHeight();
const playerAspectRatio = playerWidth / playerHeight;
const videoAspectRatio = this.player_.videoWidth() / this.player_.videoHeight();
let insetInlineMatch = 0;
let insetBlockMatch = 0;

if (Math.abs(playerAspectRatio - videoAspectRatio) > 0.1) {
if (playerAspectRatio > videoAspectRatio) {
insetInlineMatch = Math.round((playerWidth - playerHeight * videoAspectRatio) / 2);
} else {
insetBlockMatch = Math.round((playerHeight - playerWidth / videoAspectRatio) / 2);
}
}

tryUpdateStyle(this.el_, 'insetInline', getCSSPositionValue(insetInlineMatch));
tryUpdateStyle(this.el_, 'insetBlock', getCSSPositionValue(insetBlockMatch));
}

/**
* Style {@Link TextTrack} activeCues according to {@Link TextTrackSettings}.
*
Expand Down
49 changes: 49 additions & 0 deletions test/unit/tracks/text-track-display.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,53 @@ if (!Html5.supportsNativeTextTracks()) {
'colors must be valid hex codes.'
);
});

QUnit.test('text track display should overlay a video', function(assert) {
const tag = document.createElement('video');

tag.width = 320;
tag.height = 180;
const player = TestHelpers.makePlayer({}, tag);
const textTrackDisplay = player.getChild('TextTrackDisplay');
const textTrackDisplayStyle = textTrackDisplay.el().style;

assert.ok(textTrackDisplayStyle.insetInline === '', 'text track display style insetInline equal to empty string');
assert.ok(textTrackDisplayStyle.insetBlock === '', 'text track display style insetBlock equal to empty string');

// video aspect ratio equal to NaN
player.tech_.videoWidth = () => 0;
player.tech_.videoHeight = () => 0;

assert.ok(textTrackDisplayStyle.insetInline === '', 'text track display style insetInline equal to empty string');
assert.ok(textTrackDisplayStyle.insetBlock === '', 'text track display style insetBlock equal to empty string');

// video aspect ratio 2:1
player.tech_.videoWidth = () => 100;
player.tech_.videoHeight = () => 50;

textTrackDisplay.updateDisplayOverlay();

assert.ok(textTrackDisplayStyle.insetInline === '', 'text track display style insetInline equal to empty string');
assert.ok(textTrackDisplayStyle.insetBlock === '10px', 'text track display style insetBlock equal to 10px');

// video aspect ratio 4:3
player.tech_.videoWidth = () => 100;
player.tech_.videoHeight = () => 75;

textTrackDisplay.updateDisplayOverlay();

assert.ok(textTrackDisplayStyle.insetInline === '40px', 'text track display style insetInline equal to 40px');
assert.ok(textTrackDisplayStyle.insetBlock === '', 'text track display style insetBlock equal to empty string');

// video aspect ratio 16:9
player.tech_.videoWidth = () => 320;
player.tech_.videoHeight = () => 180;

textTrackDisplay.updateDisplayOverlay();

assert.ok(textTrackDisplayStyle.insetInline === '', 'text track display style insetInline equal to empty string');
assert.ok(textTrackDisplayStyle.insetBlock === '', 'text track display style insetBlock equal to empty string');

player.dispose();
});
}

0 comments on commit 1491d71

Please sign in to comment.