-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add a mouse volume tooltip (#6824)
- Loading branch information
1 parent
239c9a1
commit b2edfd2
Showing
5 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
src/js/control-bar/volume-control/mouse-volume-level-display.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* @file mouse-volume-level-display.js | ||
*/ | ||
import Component from '../../component.js'; | ||
import * as Fn from '../../utils/fn.js'; | ||
|
||
import './volume-level-tooltip'; | ||
|
||
/** | ||
* The {@link MouseVolumeLevelDisplay} component tracks mouse movement over the | ||
* {@link VolumeControl}. It displays an indicator and a {@link VolumeLevelTooltip} | ||
* indicating the volume level which is represented by a given point in the | ||
* {@link VolumeBar}. | ||
* | ||
* @extends Component | ||
*/ | ||
class MouseVolumeLevelDisplay extends Component { | ||
|
||
/** | ||
* Creates an instance of this class. | ||
* | ||
* @param {Player} player | ||
* The {@link Player} that this class should be attached to. | ||
* | ||
* @param {Object} [options] | ||
* The key/value store of player options. | ||
*/ | ||
constructor(player, options) { | ||
super(player, options); | ||
this.update = Fn.throttle(Fn.bind(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); | ||
} | ||
|
||
/** | ||
* Create the DOM element for this class. | ||
* | ||
* @return {Element} | ||
* The element that was created. | ||
*/ | ||
createEl() { | ||
return super.createEl('div', { | ||
className: 'vjs-mouse-display' | ||
}); | ||
} | ||
|
||
/** | ||
* Enquires updates to its own DOM as well as the DOM of its | ||
* {@link VolumeLevelTooltip} child. | ||
* | ||
* @param {Object} rangeBarRect | ||
* The `ClientRect` for the {@link VolumeBar} element. | ||
* | ||
* @param {number} rangeBarPoint | ||
* A number from 0 to 1, representing a horizontal/vertical reference point | ||
* from the left edge of the {@link VolumeBar} | ||
* | ||
* @param {boolean} vertical | ||
* Referees to the Volume control position | ||
* in the control bar{@link VolumeControl} | ||
* | ||
*/ | ||
update(rangeBarRect, rangeBarPoint, vertical) { | ||
const volume = 100 * rangeBarPoint; | ||
|
||
this.getChild('volumeLevelTooltip').updateVolume(rangeBarRect, rangeBarPoint, vertical, volume, () => { | ||
if (vertical) { | ||
this.el_.style.bottom = `${rangeBarRect.height * rangeBarPoint}px`; | ||
} else { | ||
this.el_.style.left = `${rangeBarRect.width * rangeBarPoint}px`; | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Default options for `MouseVolumeLevelDisplay` | ||
* | ||
* @type {Object} | ||
* @private | ||
*/ | ||
MouseVolumeLevelDisplay.prototype.options_ = { | ||
children: [ | ||
'volumeLevelTooltip' | ||
] | ||
}; | ||
|
||
Component.registerComponent('MouseVolumeLevelDisplay', MouseVolumeLevelDisplay); | ||
export default MouseVolumeLevelDisplay; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
src/js/control-bar/volume-control/volume-level-tooltip.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/** | ||
* @file volume-level-tooltip.js | ||
*/ | ||
import Component from '../../component'; | ||
import * as Dom from '../../utils/dom.js'; | ||
import * as Fn from '../../utils/fn.js'; | ||
|
||
/** | ||
* Volume level tooltips display a volume above or side by side the volume bar. | ||
* | ||
* @extends Component | ||
*/ | ||
class VolumeLevelTooltip extends Component { | ||
|
||
/** | ||
* Creates an instance of this class. | ||
* | ||
* @param {Player} player | ||
* The {@link Player} that this class should be attached to. | ||
* | ||
* @param {Object} [options] | ||
* The key/value store of player options. | ||
*/ | ||
constructor(player, options) { | ||
super(player, options); | ||
this.update = Fn.throttle(Fn.bind(this, this.update), Fn.UPDATE_REFRESH_INTERVAL); | ||
} | ||
|
||
/** | ||
* Create the volume tooltip DOM element | ||
* | ||
* @return {Element} | ||
* The element that was created. | ||
*/ | ||
createEl() { | ||
return super.createEl('div', { | ||
className: 'vjs-volume-tooltip' | ||
}, { | ||
'aria-hidden': 'true' | ||
}); | ||
} | ||
|
||
/** | ||
* Updates the position of the tooltip relative to the `VolumeBar` and | ||
* its content text. | ||
* | ||
* @param {Object} rangeBarRect | ||
* The `ClientRect` for the {@link VolumeBar} element. | ||
* | ||
* @param {number} rangeBarPoint | ||
* A number from 0 to 1, representing a horizontal/vertical reference point | ||
* from the left edge of the {@link VolumeBar} | ||
* | ||
* @param {boolean} vertical | ||
* Referees to the Volume control position | ||
* in the control bar{@link VolumeControl} | ||
* | ||
*/ | ||
update(rangeBarRect, rangeBarPoint, vertical, content) { | ||
if (!vertical) { | ||
const tooltipRect = Dom.getBoundingClientRect(this.el_); | ||
const playerRect = Dom.getBoundingClientRect(this.player_.el()); | ||
const volumeBarPointPx = rangeBarRect.width * rangeBarPoint; | ||
|
||
if (!playerRect || !tooltipRect) { | ||
return; | ||
} | ||
|
||
const spaceLeftOfPoint = (rangeBarRect.left - playerRect.left) + volumeBarPointPx; | ||
const spaceRightOfPoint = (rangeBarRect.width - volumeBarPointPx) + | ||
(playerRect.right - rangeBarRect.right); | ||
let pullTooltipBy = tooltipRect.width / 2; | ||
|
||
if (spaceLeftOfPoint < pullTooltipBy) { | ||
pullTooltipBy += pullTooltipBy - spaceLeftOfPoint; | ||
} else if (spaceRightOfPoint < pullTooltipBy) { | ||
pullTooltipBy = spaceRightOfPoint; | ||
} | ||
|
||
if (pullTooltipBy < 0) { | ||
pullTooltipBy = 0; | ||
} else if (pullTooltipBy > tooltipRect.width) { | ||
pullTooltipBy = tooltipRect.width; | ||
} | ||
|
||
this.el_.style.right = `-${pullTooltipBy}px`; | ||
} | ||
this.write(`${content}%`); | ||
} | ||
|
||
/** | ||
* Write the volume to the tooltip DOM element. | ||
* | ||
* @param {string} content | ||
* The formatted volume for the tooltip. | ||
*/ | ||
write(content) { | ||
Dom.textContent(this.el_, content); | ||
} | ||
|
||
/** | ||
* Updates the position of the volume tooltip relative to the `VolumeBar`. | ||
* | ||
* @param {Object} rangeBarRect | ||
* The `ClientRect` for the {@link VolumeBar} element. | ||
* | ||
* @param {number} rangeBarPoint | ||
* A number from 0 to 1, representing a horizontal/vertical reference point | ||
* from the left edge of the {@link VolumeBar} | ||
* | ||
* @param {boolean} vertical | ||
* Referees to the Volume control position | ||
* in the control bar{@link VolumeControl} | ||
* | ||
* @param {number} volume | ||
* The volume level to update the tooltip to | ||
* | ||
* @param {Function} cb | ||
* A function that will be called during the request animation frame | ||
* for tooltips that need to do additional animations from the default | ||
*/ | ||
updateVolume(rangeBarRect, rangeBarPoint, vertical, volume, cb) { | ||
this.requestNamedAnimationFrame('VolumeLevelTooltip#updateVolume', () => { | ||
this.update(rangeBarRect, rangeBarPoint, vertical, volume.toFixed(0)); | ||
if (cb) { | ||
cb(); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
Component.registerComponent('VolumeLevelTooltip', VolumeLevelTooltip); | ||
export default VolumeLevelTooltip; |