feat: tweaks to markers logic and design
This commit is contained in:
parent
565b68a5e2
commit
1d4869beee
@ -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',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
128
src/js/controls.js
vendored
128
src/js/controls.js
vendored
@ -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);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)) {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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';
|
||||||
|
@ -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;
|
|
@ -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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user