feat: tweaks to markers logic and design

This commit is contained in:
Sam Potts 2022-04-18 20:15:23 +10:00
parent 565b68a5e2
commit 1d4869beee
11 changed files with 127 additions and 148 deletions

View File

@ -81,15 +81,15 @@ import toggleClass from './toggle-class';
points: [ points: [
{ {
time: 10, time: 10,
tip: 'first marker', label: 'first marker',
}, },
{ {
time: 40, time: 40,
tip: 'second marker', label: 'second marker',
}, },
{ {
time: 120, time: 120,
tipHTML: '<strong>third</strong> marker', label: '<strong>third</strong> marker',
}, },
], ],
}, },

View File

@ -350,6 +350,7 @@ const defaults = {
hover: 'plyr--hover', hover: 'plyr--hover',
tooltip: 'plyr__tooltip', tooltip: 'plyr__tooltip',
cues: 'plyr__cues', cues: 'plyr__cues',
marker: 'plyr__progress__marker',
hidden: 'plyr__sr-only', hidden: 'plyr__sr-only',
hideControls: 'plyr--hide-controls', hideControls: 'plyr--hide-controls',
isIos: 'plyr--is-ios', isIos: 'plyr--is-ios',
@ -391,10 +392,6 @@ const defaults = {
scrubbingContainer: 'plyr__preview-scrubbing', scrubbingContainer: 'plyr__preview-scrubbing',
scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown', scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',
}, },
markers: {
points: 'plyr__marker__points',
tip: 'plyr__marker__tip',
},
}, },
// Embed attributes // Embed attributes
@ -453,7 +450,7 @@ const defaults = {
album: '', album: '',
artwork: [], artwork: [],
}, },
// Markers // Markers
markers: { markers: {
enabled: false, enabled: false,

134
src/js/controls.js vendored
View File

@ -484,7 +484,7 @@ const controls = {
menuItem.appendChild(flex); menuItem.appendChild(flex);
// Replicate radio button behaviour // Replicate radio button behavior
Object.defineProperty(menuItem, 'checked', { Object.defineProperty(menuItem, 'checked', {
enumerable: true, enumerable: true,
get() { get() {
@ -698,8 +698,9 @@ const controls = {
return; return;
} }
const tipElement = this.elements.display.seekTooltip;
const visible = `${this.config.classNames.tooltip}--visible`; const visible = `${this.config.classNames.tooltip}--visible`;
const toggle = (show) => toggleClass(this.elements.display.seekTooltip, visible, show); const toggle = (show) => toggleClass(tipElement, visible, show);
// Hide on touch // Hide on touch
if (this.touch) { if (this.touch) {
@ -713,8 +714,8 @@ const controls = {
if (is.event(event)) { if (is.event(event)) {
percent = (100 / clientRect.width) * (event.pageX - clientRect.left); percent = (100 / clientRect.width) * (event.pageX - clientRect.left);
} else if (hasClass(this.elements.display.seekTooltip, visible)) { } else if (hasClass(tipElement, visible)) {
percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); percent = parseFloat(tipElement.style.left, 10);
} else { } else {
return; return;
} }
@ -726,11 +727,21 @@ const controls = {
percent = 100; percent = 100;
} }
const time = (this.duration / 100) * percent;
// Display the time a click would seek to // Display the time a click would seek to
controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent); tipElement.innerText = controls.formatTime(time);
// Get marker point for time
const point = this.config.markers?.points?.find(({ time: t }) => t === Math.round(time));
// Append the point label to the tooltip
if (point) {
tipElement.insertAdjacentHTML('afterbegin', `${point.label}<br>`);
}
// Set position // Set position
this.elements.display.seekTooltip.style.left = `${percent}%`; tipElement.style.left = `${percent}%`;
// Show/hide the tooltip // Show/hide the tooltip
// If the event is a moues in/out and percentage is inside bounds // If the event is a moues in/out and percentage is inside bounds
@ -1761,70 +1772,81 @@ const controls = {
artwork: this.config.mediaMetadata.artwork, artwork: this.config.mediaMetadata.artwork,
}); });
} }
// eslint-disable-next-line no-empty } catch (_) {
} catch (e) {} // Do nothing
}, }
},
// Add markers
// Add markers
setMarkers() { setMarkers() {
if (this.duration > 0 && !this.elements.markers) { if (!this.duration || this.elements.markers) return;
const { points } = this.config.markers;
const markersContainerFragment = document.createDocumentFragment(); // Get valid points
const markersPointsFragment = document.createDocumentFragment(); const points = this.config.markers?.points?.filter(({ time }) => time > 0 && time < this.duration);
const markerTipElement = createElement( if (!points?.length) return;
const containerFragment = document.createDocumentFragment();
const pointsFragment = document.createDocumentFragment();
let tipElement = null;
const tipVisible = `${this.config.classNames.tooltip}--visible`;
const toggleTip = (show) => toggleClass(tipElement, tipVisible, show);
// Inject markers to progress container
points.forEach((point) => {
const markerElement = createElement(
'span', 'span',
{ {
class: this.config.classNames.markers.tip, class: this.config.classNames.marker,
}, },
'', '',
); );
points.forEach((point) => { const left = `${(point.time / this.duration) * 100}%`;
if (point < 0 || point > this.duration) {
return;
}
const markerPointElement = createElement( if (tipElement) {
'span', // Show on hover
{ markerElement.addEventListener('mouseenter', () => {
class: this.config.classNames.markers.points, if (point.label) return;
}, tipElement.style.left = left;
'', tipElement.innerHTML = point.label;
); toggleTip(true);
const left = `${(point.time / this.duration) * 100}%`;
const tipVisible = `${this.config.classNames.markers.tip}--visible`;
const toggle = (show) => toggleClass(markerTipElement, tipVisible, show);
markerPointElement.addEventListener('mouseenter', () => {
markerTipElement.style.left = left;
if (point.tipHTML) {
markerTipElement.innerHTML = point.tipHTML;
} else {
markerTipElement.innerText = point.tip;
}
toggle(true);
});
markerPointElement.addEventListener('mouseleave', () => {
toggle(false);
});
markerPointElement.addEventListener('click', () => {
this.currentTime = point.time;
}); });
markerPointElement.style.left = left; // Hide on leave
markersPointsFragment.appendChild(markerPointElement); markerElement.addEventListener('mouseleave', () => {
toggleTip(false);
});
}
markerElement.addEventListener('click', () => {
this.currentTime = point.time;
}); });
markersContainerFragment.appendChild(markersPointsFragment); markerElement.style.left = left;
markersContainerFragment.appendChild(markerTipElement); pointsFragment.appendChild(markerElement);
});
this.elements.markers = { containerFragment.appendChild(pointsFragment);
points: markersPointsFragment,
tip: markerTipElement, // Inject a tooltip if needed
}; if (!this.config.tooltips.seek) {
this.elements.progress.appendChild(markersContainerFragment); tipElement = createElement(
'span',
{
class: this.config.classNames.tooltip,
},
'',
);
containerFragment.appendChild(tipElement);
} }
this.elements.markers = {
points: pointsFragment,
tip: tipElement,
};
this.elements.progress.appendChild(containerFragment);
}, },
}; };

View File

@ -241,6 +241,15 @@ class PreviewThumbnails {
// Set time text inside image container // Set time text inside image container
this.elements.thumb.time.innerText = formatTime(this.seekTime); this.elements.thumb.time.innerText = formatTime(this.seekTime);
// Get marker point for time
const point = this.player.config.markers?.points?.find(({ time: t }) => t === Math.round(this.seekTime));
// Append the point label to the tooltip
if (point) {
// this.elements.thumb.time.innerText.concat('\n');
this.elements.thumb.time.insertAdjacentHTML('afterbegin', `${point.label}<br>`);
}
} }
// Download and show image // Download and show image
@ -326,7 +335,7 @@ class PreviewThumbnails {
this.elements.thumb.time = createElement('span', {}, '00:00'); this.elements.thumb.time = createElement('span', {}, '00:00');
timeContainer.appendChild(this.elements.thumb.time); timeContainer.appendChild(this.elements.thumb.time);
this.elements.thumb.container.appendChild(timeContainer); this.elements.thumb.imageContainer.appendChild(timeContainer);
// Inject the whole thumb // Inject the whole thumb
if (is.element(this.player.elements.progress)) { if (is.element(this.player.elements.progress)) {

View File

@ -1,57 +0,0 @@
// --------------------------------------------------------------
// Markers
// --------------------------------------------------------------
.plyr__marker__points {
width: $plyr-range-track-height;
height: $plyr-range-track-height;
border-radius: $plyr-range-track-height;
background-color: #fff;
position: absolute;
top: 50%;
margin-top: calc((#{$plyr-range-track-height} / 2) * -1);
margin-left: calc((#{$plyr-range-track-height} / 2) * -1);
z-index: 3;
}
.plyr__marker__tip {
background: $plyr-markers-background;
border-radius: $plyr-markers-radius;
bottom: 100%;
box-shadow: $plyr-markers-shadow;
color: $plyr-markers-color;
font-size: $plyr-font-size-small;
font-weight: $plyr-font-weight-regular;
left: 50%;
line-height: 1.3;
margin-bottom: calc(#{$plyr-markers-padding} * 2);
opacity: 0;
padding: $plyr-markers-padding calc(#{$plyr-markers-padding} * 1.5);
pointer-events: none;
position: absolute;
transform: translate(-50%, 10px) scale(0.8);
transform-origin: 50% 100%;
transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease;
white-space: nowrap;
z-index: 2;
// The background triangle
&::before {
border-left: $plyr-markers-arrow-size solid transparent;
border-right: $plyr-markers-arrow-size solid transparent;
border-top: $plyr-markers-arrow-size solid $plyr-markers-background;
bottom: calc(#{$plyr-markers-arrow-size} * -1);
content: '';
height: 0;
left: 50%;
position: absolute;
transform: translateX(-50%);
width: 0;
z-index: 2;
}
}
.plyr__marker__tip--visible {
opacity: 1;
transform: translate(-50%, 0) scale(1);
z-index: 3;
}

View File

@ -24,8 +24,10 @@ $plyr-progress-offset: $plyr-range-thumb-height;
// Seek tooltip to show time // Seek tooltip to show time
.plyr__tooltip { .plyr__tooltip {
font-size: $plyr-font-size-time;
left: 0; left: 0;
max-width: 120px;
overflow-wrap: break-word;
white-space: normal;
} }
} }
@ -92,3 +94,15 @@ $plyr-progress-offset: $plyr-range-thumb-height;
.plyr--audio.plyr--loading .plyr__progress__buffer { .plyr--audio.plyr--loading .plyr__progress__buffer {
background-color: $plyr-audio-progress-buffered-background; background-color: $plyr-audio-progress-buffered-background;
} }
// Markers
.plyr__progress__marker {
background-color: $plyr-progress-marker-background;
border-radius: 1px;
height: $plyr-range-track-height;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: $plyr-progress-marker-width;
z-index: 3;
}

View File

@ -6,12 +6,12 @@
.plyr__preview-thumb { .plyr__preview-thumb {
background-color: $plyr-preview-background; background-color: $plyr-preview-background;
border-radius: 3px; border-radius: $plyr-preview-radius;
bottom: 100%; bottom: 100%;
box-shadow: $plyr-preview-shadow; box-shadow: $plyr-preview-shadow;
margin-bottom: calc(#{$plyr-preview-padding} * 2); margin-bottom: calc(#{$plyr-preview-padding} * 2);
opacity: 0; opacity: 0;
padding: $plyr-preview-radius; padding: 3px;
pointer-events: none; pointer-events: none;
position: absolute; position: absolute;
transform: translate(0, 10px) scale(0.8); transform: translate(0, 10px) scale(0.8);
@ -59,19 +59,20 @@
// Seek time text // Seek time text
&__time-container { &__time-container {
bottom: $plyr-preview-time-bottom-offset; background: $plyr-preview-time-container-background;
border-bottom-left-radius: calc(#{$plyr-preview-radius} - 1px);
border-bottom-right-radius: calc(#{$plyr-preview-radius} - 1px);
bottom: 0;
left: 0; left: 0;
line-height: 1.1;
padding: $plyr-preview-time-container-padding;
position: absolute; position: absolute;
right: 0; right: 0;
white-space: nowrap;
z-index: 3; z-index: 3;
span { span {
background-color: $plyr-preview-time-background;
border-radius: calc(#{$plyr-preview-radius} - 1px);
color: $plyr-preview-time-color; color: $plyr-preview-time-color;
font-size: $plyr-preview-time-font-size; font-size: $plyr-preview-time-font-size;
padding: $plyr-preview-time-padding;
} }
} }
} }

View File

@ -4,12 +4,14 @@
$plyr-preview-padding: $plyr-tooltip-padding !default; $plyr-preview-padding: $plyr-tooltip-padding !default;
$plyr-preview-background: $plyr-tooltip-background !default; $plyr-preview-background: $plyr-tooltip-background !default;
$plyr-preview-radius: $plyr-tooltip-radius !default; $plyr-preview-radius: 6px !default;
$plyr-preview-shadow: $plyr-tooltip-shadow !default; $plyr-preview-shadow: $plyr-tooltip-shadow !default;
$plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default; $plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default;
$plyr-preview-image-background: $plyr-color-gray-200 !default; $plyr-preview-image-background: $plyr-color-gray-200 !default;
$plyr-preview-time-font-size: $plyr-font-size-time !default; $plyr-preview-time-container-background: var(
$plyr-preview-time-padding: 3px 6px !default; --plyr-video-controls-background,
$plyr-preview-time-background: rgba(0, 0, 0, 0.55); linear-gradient(rgba(#000, 0), rgba(#000, 0.75))
) !default;
$plyr-preview-time-container-padding: 20px 6px 6px !default;
$plyr-preview-time-color: #fff; $plyr-preview-time-color: #fff;
$plyr-preview-time-bottom-offset: 6px; $plyr-preview-time-font-size: $plyr-font-size-time !default;

View File

@ -20,7 +20,6 @@ $css-vars-use-native: true;
@import 'settings/progress'; @import 'settings/progress';
@import 'settings/sliders'; @import 'settings/sliders';
@import 'settings/tooltips'; @import 'settings/tooltips';
@import 'settings/markers';
@import 'lib/animation'; @import 'lib/animation';
@import 'lib/functions'; @import 'lib/functions';
@import 'lib/mixins'; @import 'lib/mixins';
@ -36,7 +35,6 @@ $css-vars-use-native: true;
@import 'components/tooltips'; @import 'components/tooltips';
@import 'components/progress'; @import 'components/progress';
@import 'components/volume'; @import 'components/volume';
@import 'components/markers';
@import 'types/audio'; @import 'types/audio';
@import 'types/video'; @import 'types/video';
@import 'states/fullscreen'; @import 'states/fullscreen';

View File

@ -1,11 +0,0 @@
// ==========================================================================
// Markers
// ==========================================================================
$plyr-markers-background: var(--plyr-markers-background, rgba(#fff, 0.9)) !default;
$plyr-markers-color: var(--plyr-markers-color, $plyr-color-gray-700) !default;
$plyr-markers-padding: calc(#{$plyr-control-spacing} / 2);
$plyr-markers-padding: var(--plyr-markers-padding, $plyr-markers-padding) !default;
$plyr-markers-arrow-size: var(--plyr-markers-arrow-size, 4px) !default;
$plyr-markers-radius: var(--plyr-markers-radius, 3px) !default;
$plyr-markers-shadow: var(--plyr-markers-shadow, 0 1px 2px rgba(0, 0, 0, 0.15)) !default;

View File

@ -6,6 +6,10 @@
$plyr-progress-loading-size: var(--plyr-progress-loading-size, 25px) !default; $plyr-progress-loading-size: var(--plyr-progress-loading-size, 25px) !default;
$plyr-progress-loading-background: var(--plyr-progress-loading-background, rgba($plyr-color-gray-900, 0.6)) !default; $plyr-progress-loading-background: var(--plyr-progress-loading-background, rgba($plyr-color-gray-900, 0.6)) !default;
// Markers
$plyr-progress-marker-background: var(--plyr-progress-marker-background, #fff) !default;
$plyr-progress-marker-width: var(--plyr-progress-marker-width, 3px) !default;
// Buffered // Buffered
$plyr-video-progress-buffered-background: var(--plyr-video-progress-buffered-background, rgba(#fff, 0.25)) !default; $plyr-video-progress-buffered-background: var(--plyr-video-progress-buffered-background, rgba(#fff, 0.25)) !default;
$plyr-audio-progress-buffered-background: var( $plyr-audio-progress-buffered-background: var(