您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Audio.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // @flow
  2. import React from 'react';
  3. import AbstractAudio from '../AbstractAudio';
  4. import type { AudioElement } from '../AbstractAudio';
  5. /**
  6. * The React/Web {@link Component} which is similar to and wraps around
  7. * {@code HTMLAudioElement} in order to facilitate cross-platform source code.
  8. */
  9. export default class Audio extends AbstractAudio {
  10. /**
  11. * Set to <code>true</code> when the whole file is loaded.
  12. */
  13. _audioFileLoaded: boolean;
  14. /**
  15. * Reference to the HTML audio element, stored until the file is ready.
  16. */
  17. _ref: ?AudioElement;
  18. /**
  19. * Creates new <code>Audio</code> element instance with given props.
  20. *
  21. * @param {Object} props - The read-only properties with which the new
  22. * instance is to be initialized.
  23. */
  24. constructor(props: Object) {
  25. super(props);
  26. // Bind event handlers so they are only bound once for every instance.
  27. this._onCanPlayThrough = this._onCanPlayThrough.bind(this);
  28. this._setRef = this._setRef.bind(this);
  29. }
  30. /**
  31. * Implements React's {@link Component#render()}.
  32. *
  33. * @inheritdoc
  34. * @returns {ReactElement}
  35. */
  36. render() {
  37. const loop = this.props.loop ? 'true' : null;
  38. return (
  39. <audio
  40. loop = { loop }
  41. onCanPlayThrough = { this._onCanPlayThrough }
  42. preload = 'auto'
  43. // $FlowFixMe
  44. ref = { this._setRef }
  45. src = { this.props.src } />
  46. );
  47. }
  48. /**
  49. * Stops the audio HTML element.
  50. *
  51. * @returns {void}
  52. */
  53. stop() {
  54. if (this._ref) {
  55. this._ref.pause();
  56. // $FlowFixMe
  57. this._ref.currentTime = 0;
  58. }
  59. }
  60. /**
  61. * If audio element reference has been set and the file has been
  62. * loaded then {@link setAudioElementImpl} will be called to eventually add
  63. * the audio to the Redux store.
  64. *
  65. * @private
  66. * @returns {void}
  67. */
  68. _maybeSetAudioElementImpl() {
  69. if (this._ref && this._audioFileLoaded) {
  70. this.setAudioElementImpl(this._ref);
  71. }
  72. }
  73. _onCanPlayThrough: () => void;
  74. /**
  75. * Called when 'canplaythrough' event is triggered on the audio element,
  76. * which means that the whole file has been loaded.
  77. *
  78. * @private
  79. * @returns {void}
  80. */
  81. _onCanPlayThrough() {
  82. this._audioFileLoaded = true;
  83. this._maybeSetAudioElementImpl();
  84. }
  85. _setRef: (?AudioElement) => void;
  86. /**
  87. * Sets the reference to the HTML audio element.
  88. *
  89. * @param {HTMLAudioElement} audioElement - The HTML audio element instance.
  90. * @private
  91. * @returns {void}
  92. */
  93. _setRef(audioElement: ?AudioElement) {
  94. this._ref = audioElement;
  95. if (audioElement) {
  96. this._maybeSetAudioElementImpl();
  97. } else {
  98. // AbstractAudioElement is supposed to trigger "removeAudio" only if
  99. // it was previously added, so it's safe to just call it.
  100. this.setAudioElementImpl(null);
  101. // Reset the loaded flag, as the audio element is being removed from
  102. // the DOM tree.
  103. this._audioFileLoaded = false;
  104. }
  105. }
  106. }