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.js 2.3KB

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