feat: tweaks to markers logic and design
This commit is contained in:
		| @ -81,15 +81,15 @@ import toggleClass from './toggle-class'; | ||||
|         points: [ | ||||
|           { | ||||
|             time: 10, | ||||
|             tip: 'first marker', | ||||
|             label: 'first marker', | ||||
|           }, | ||||
|           { | ||||
|             time: 40, | ||||
|             tip: 'second marker', | ||||
|             label: 'second marker', | ||||
|           }, | ||||
|           { | ||||
|             time: 120, | ||||
|             tipHTML: '<strong>third</strong> marker', | ||||
|             label: '<strong>third</strong> marker', | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|  | ||||
| @ -350,6 +350,7 @@ const defaults = { | ||||
|     hover: 'plyr--hover', | ||||
|     tooltip: 'plyr__tooltip', | ||||
|     cues: 'plyr__cues', | ||||
|     marker: 'plyr__progress__marker', | ||||
|     hidden: 'plyr__sr-only', | ||||
|     hideControls: 'plyr--hide-controls', | ||||
|     isIos: 'plyr--is-ios', | ||||
| @ -391,10 +392,6 @@ const defaults = { | ||||
|       scrubbingContainer: 'plyr__preview-scrubbing', | ||||
|       scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown', | ||||
|     }, | ||||
|     markers: { | ||||
|       points: 'plyr__marker__points', | ||||
|       tip: 'plyr__marker__tip', | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   // Embed attributes | ||||
| @ -453,7 +450,7 @@ const defaults = { | ||||
|     album: '', | ||||
|     artwork: [], | ||||
|   }, | ||||
|    | ||||
|  | ||||
|   // Markers | ||||
|   markers: { | ||||
|     enabled: false, | ||||
|  | ||||
							
								
								
									
										134
									
								
								src/js/controls.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										134
									
								
								src/js/controls.js
									
									
									
									
										vendored
									
									
								
							| @ -484,7 +484,7 @@ const controls = { | ||||
|  | ||||
|     menuItem.appendChild(flex); | ||||
|  | ||||
|     // Replicate radio button behaviour | ||||
|     // Replicate radio button behavior | ||||
|     Object.defineProperty(menuItem, 'checked', { | ||||
|       enumerable: true, | ||||
|       get() { | ||||
| @ -698,8 +698,9 @@ const controls = { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     const tipElement = this.elements.display.seekTooltip; | ||||
|     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 | ||||
|     if (this.touch) { | ||||
| @ -713,8 +714,8 @@ const controls = { | ||||
|  | ||||
|     if (is.event(event)) { | ||||
|       percent = (100 / clientRect.width) * (event.pageX - clientRect.left); | ||||
|     } else if (hasClass(this.elements.display.seekTooltip, visible)) { | ||||
|       percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); | ||||
|     } else if (hasClass(tipElement, visible)) { | ||||
|       percent = parseFloat(tipElement.style.left, 10); | ||||
|     } else { | ||||
|       return; | ||||
|     } | ||||
| @ -726,11 +727,21 @@ const controls = { | ||||
|       percent = 100; | ||||
|     } | ||||
|  | ||||
|     const time = (this.duration / 100) * percent; | ||||
|  | ||||
|     // 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 | ||||
|     this.elements.display.seekTooltip.style.left = `${percent}%`; | ||||
|     tipElement.style.left = `${percent}%`; | ||||
|  | ||||
|     // Show/hide the tooltip | ||||
|     // If the event is a moues in/out and percentage is inside bounds | ||||
| @ -1761,70 +1772,81 @@ const controls = { | ||||
|           artwork: this.config.mediaMetadata.artwork, | ||||
|         }); | ||||
|       } | ||||
|       // eslint-disable-next-line no-empty | ||||
|     } catch (e) {} | ||||
|   },  | ||||
|      | ||||
|   // Add markers  | ||||
|     } catch (_) { | ||||
|       // Do nothing | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   // Add markers | ||||
|   setMarkers() { | ||||
|     if (this.duration > 0 && !this.elements.markers) { | ||||
|       const { points } = this.config.markers; | ||||
|       const markersContainerFragment = document.createDocumentFragment(); | ||||
|       const markersPointsFragment = document.createDocumentFragment(); | ||||
|       const markerTipElement = createElement( | ||||
|     if (!this.duration || this.elements.markers) return; | ||||
|  | ||||
|     // Get valid points | ||||
|     const points = this.config.markers?.points?.filter(({ time }) => time > 0 && time < this.duration); | ||||
|     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', | ||||
|         { | ||||
|           class: this.config.classNames.markers.tip, | ||||
|           class: this.config.classNames.marker, | ||||
|         }, | ||||
|         '', | ||||
|       ); | ||||
|  | ||||
|       points.forEach((point) => { | ||||
|         if (point < 0 || point > this.duration) { | ||||
|           return; | ||||
|         } | ||||
|       const left = `${(point.time / this.duration) * 100}%`; | ||||
|  | ||||
|         const markerPointElement = createElement( | ||||
|           'span', | ||||
|           { | ||||
|             class: this.config.classNames.markers.points, | ||||
|           }, | ||||
|           '', | ||||
|         ); | ||||
|  | ||||
|         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; | ||||
|       if (tipElement) { | ||||
|         // Show on hover | ||||
|         markerElement.addEventListener('mouseenter', () => { | ||||
|           if (point.label) return; | ||||
|           tipElement.style.left = left; | ||||
|           tipElement.innerHTML = point.label; | ||||
|           toggleTip(true); | ||||
|         }); | ||||
|  | ||||
|         markerPointElement.style.left = left; | ||||
|         markersPointsFragment.appendChild(markerPointElement); | ||||
|         // Hide on leave | ||||
|         markerElement.addEventListener('mouseleave', () => { | ||||
|           toggleTip(false); | ||||
|         }); | ||||
|       } | ||||
|  | ||||
|       markerElement.addEventListener('click', () => { | ||||
|         this.currentTime = point.time; | ||||
|       }); | ||||
|  | ||||
|       markersContainerFragment.appendChild(markersPointsFragment); | ||||
|       markersContainerFragment.appendChild(markerTipElement); | ||||
|       markerElement.style.left = left; | ||||
|       pointsFragment.appendChild(markerElement); | ||||
|     }); | ||||
|  | ||||
|       this.elements.markers = { | ||||
|         points: markersPointsFragment, | ||||
|         tip: markerTipElement, | ||||
|       }; | ||||
|       this.elements.progress.appendChild(markersContainerFragment); | ||||
|     containerFragment.appendChild(pointsFragment); | ||||
|  | ||||
|     // Inject a tooltip if needed | ||||
|     if (!this.config.tooltips.seek) { | ||||
|       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 | ||||
|       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 | ||||
| @ -326,7 +335,7 @@ class PreviewThumbnails { | ||||
|     this.elements.thumb.time = createElement('span', {}, '00:00'); | ||||
|     timeContainer.appendChild(this.elements.thumb.time); | ||||
|  | ||||
|     this.elements.thumb.container.appendChild(timeContainer); | ||||
|     this.elements.thumb.imageContainer.appendChild(timeContainer); | ||||
|  | ||||
|     // Inject the whole thumb | ||||
|     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 | ||||
|   .plyr__tooltip { | ||||
|     font-size: $plyr-font-size-time; | ||||
|     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 { | ||||
|   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 { | ||||
|   background-color: $plyr-preview-background; | ||||
|   border-radius: 3px; | ||||
|   border-radius: $plyr-preview-radius; | ||||
|   bottom: 100%; | ||||
|   box-shadow: $plyr-preview-shadow; | ||||
|   margin-bottom: calc(#{$plyr-preview-padding} * 2); | ||||
|   opacity: 0; | ||||
|   padding: $plyr-preview-radius; | ||||
|   padding: 3px; | ||||
|   pointer-events: none; | ||||
|   position: absolute; | ||||
|   transform: translate(0, 10px) scale(0.8); | ||||
| @ -59,19 +59,20 @@ | ||||
|  | ||||
|   // Seek time text | ||||
|   &__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; | ||||
|     line-height: 1.1; | ||||
|     padding: $plyr-preview-time-container-padding; | ||||
|     position: absolute; | ||||
|     right: 0; | ||||
|     white-space: nowrap; | ||||
|     z-index: 3; | ||||
|  | ||||
|     span { | ||||
|       background-color: $plyr-preview-time-background; | ||||
|       border-radius: calc(#{$plyr-preview-radius} - 1px); | ||||
|       color: $plyr-preview-time-color; | ||||
|       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-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-arrow-size: $plyr-tooltip-arrow-size !default; | ||||
| $plyr-preview-image-background: $plyr-color-gray-200 !default; | ||||
| $plyr-preview-time-font-size: $plyr-font-size-time !default; | ||||
| $plyr-preview-time-padding: 3px 6px !default; | ||||
| $plyr-preview-time-background: rgba(0, 0, 0, 0.55); | ||||
| $plyr-preview-time-container-background: var( | ||||
|   --plyr-video-controls-background, | ||||
|   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-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/sliders'; | ||||
| @import 'settings/tooltips'; | ||||
| @import 'settings/markers'; | ||||
| @import 'lib/animation'; | ||||
| @import 'lib/functions'; | ||||
| @import 'lib/mixins'; | ||||
| @ -36,7 +35,6 @@ $css-vars-use-native: true; | ||||
| @import 'components/tooltips'; | ||||
| @import 'components/progress'; | ||||
| @import 'components/volume'; | ||||
| @import 'components/markers'; | ||||
| @import 'types/audio'; | ||||
| @import 'types/video'; | ||||
| @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-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 | ||||
| $plyr-video-progress-buffered-background: var(--plyr-video-progress-buffered-background, rgba(#fff, 0.25)) !default; | ||||
| $plyr-audio-progress-buffered-background: var( | ||||
|  | ||||
		Reference in New Issue
	
	Block a user