You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AudioLevelIndicator.tsx 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import React, { Component } from 'react';
  2. /**
  3. * The number of dots to display in AudioLevelIndicator.
  4. *
  5. * IMPORTANT: AudioLevelIndicator assumes that this is an odd number.
  6. */
  7. const AUDIO_LEVEL_DOTS = 5;
  8. /**
  9. * The index of the dot that is at the direct middle of all other dots.
  10. */
  11. const CENTER_DOT_INDEX = Math.floor(AUDIO_LEVEL_DOTS / 2);
  12. /**
  13. * The type of the React {@code Component} props of {@link AudioLevelIndicator}.
  14. */
  15. interface IProps {
  16. /**
  17. * The current audio level to display. The value should be a number between
  18. * 0 and 1.
  19. */
  20. audioLevel: number;
  21. }
  22. /**
  23. * Creates a ReactElement responsible for drawing audio levels.
  24. *
  25. * @augments {Component}
  26. */
  27. class AudioLevelIndicator extends Component<IProps> {
  28. /**
  29. * Implements React's {@link Component#render()}.
  30. *
  31. * @inheritdoc
  32. * @returns {ReactElement}
  33. */
  34. render() {
  35. const { audioLevel: passedAudioLevel } = this.props;
  36. // First make sure we are sensitive enough.
  37. const audioLevel = typeof passedAudioLevel === 'number' && !isNaN(passedAudioLevel)
  38. ? Math.min(passedAudioLevel * 1.2, 1) : 0;
  39. // Let's now stretch the audio level over the number of dots we have.
  40. const stretchedAudioLevel = AUDIO_LEVEL_DOTS * audioLevel;
  41. const audioLevelDots = [];
  42. for (let i = 0; i < AUDIO_LEVEL_DOTS; i++) {
  43. const distanceFromCenter = CENTER_DOT_INDEX - i;
  44. const audioLevelFromCenter
  45. = stretchedAudioLevel - Math.abs(distanceFromCenter);
  46. const cappedOpacity = Math.min(
  47. 1, Math.max(0, audioLevelFromCenter));
  48. let className;
  49. if (distanceFromCenter === 0) {
  50. className = 'audiodot-middle';
  51. } else if (distanceFromCenter < 0) {
  52. className = 'audiodot-top';
  53. } else {
  54. className = 'audiodot-bottom';
  55. }
  56. audioLevelDots.push(
  57. <span
  58. className = { className }
  59. key = { i }
  60. style = {{ opacity: cappedOpacity }} />
  61. );
  62. }
  63. return (
  64. <span className = 'audioindicator in-react'>
  65. { audioLevelDots }
  66. </span>
  67. );
  68. }
  69. }
  70. export default AudioLevelIndicator;