From 4632614cedf6117febe15cfea74bc972b072050e Mon Sep 17 00:00:00 2001 From: ForeverSc Date: Sat, 12 Feb 2022 17:35:52 +0800 Subject: [PATCH] feat: add markers (#2386) Co-authored-by: fengshuo --- demo/src/js/demo.js | 17 +++++++++ src/js/config/defaults.js | 10 +++++ src/js/controls.js | 64 ++++++++++++++++++++++++++++++++ src/sass/components/markers.scss | 57 ++++++++++++++++++++++++++++ src/sass/plyr.scss | 2 + src/sass/settings/markers.scss | 11 ++++++ 6 files changed, 161 insertions(+) create mode 100644 src/sass/components/markers.scss create mode 100644 src/sass/settings/markers.scss diff --git a/demo/src/js/demo.js b/demo/src/js/demo.js index 1101fd97..ff0637e5 100644 --- a/demo/src/js/demo.js +++ b/demo/src/js/demo.js @@ -65,6 +65,23 @@ import toggleClass from './toggle-class'; // Prevent Vimeo blocking plyr.io demo site referrerPolicy: 'no-referrer', }, + markers: { + enabled: true, + points: [ + { + time: 10, + tip: 'first marker', + }, + { + time: 40, + tip: 'second marker', + }, + { + time: 120, + tipHTML: 'third marker', + }, + ], + }, }); // Expose for tinkering in the console diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index 4d64d514..582a4151 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -391,6 +391,10 @@ const defaults = { scrubbingContainer: 'plyr__preview-scrubbing', scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown', }, + markers: { + points: 'plyr__marker__points', + tip: 'plyr__marker__tip', + }, }, // Embed attributes @@ -441,6 +445,12 @@ const defaults = { customControls: true, noCookie: false, // Whether to use an alternative version of YouTube without cookies }, + + // markers + markers: { + enabled: false, + points: [], + }, }; export default defaults; diff --git a/src/js/controls.js b/src/js/controls.js index 9fe74272..35b27200 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -796,6 +796,10 @@ const controls = { controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration); } + if (this.config.markers.enabled) { + controls.setMarkers.call(this); + } + // Update the tooltip (if visible) controls.updateSeekTooltip.call(this); }, @@ -1745,6 +1749,66 @@ const controls = { }); } }, + setMarkers() { + if (this.duration > 0 && !this.elements.markers) { + const { points } = this.config.markers; + const markersContainerFragment = document.createDocumentFragment(); + const markersPointsFragment = document.createDocumentFragment(); + const markerTipElement = createElement( + 'span', + { + class: this.config.classNames.markers.tip, + }, + '', + ); + + points.forEach((point) => { + if (point < 0 || point > this.duration) { + return; + } + + 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; + }); + + markerPointElement.style.left = left; + markersPointsFragment.appendChild(markerPointElement); + }); + + markersContainerFragment.appendChild(markersPointsFragment); + markersContainerFragment.appendChild(markerTipElement); + + this.elements.markers = { + points: markersPointsFragment, + tip: markerTipElement, + }; + this.elements.progress.appendChild(markersContainerFragment); + } + }, }; export default controls; diff --git a/src/sass/components/markers.scss b/src/sass/components/markers.scss new file mode 100644 index 00000000..8030036c --- /dev/null +++ b/src/sass/components/markers.scss @@ -0,0 +1,57 @@ +// -------------------------------------------------------------- +// 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; +} \ No newline at end of file diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss index 39dc49d6..6299df74 100644 --- a/src/sass/plyr.scss +++ b/src/sass/plyr.scss @@ -20,6 +20,7 @@ $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'; @@ -35,6 +36,7 @@ $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'; diff --git a/src/sass/settings/markers.scss b/src/sass/settings/markers.scss new file mode 100644 index 00000000..4b69df96 --- /dev/null +++ b/src/sass/settings/markers.scss @@ -0,0 +1,11 @@ +// ========================================================================== +// 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;