如何解决audio.play()的问题?在React中

时间:2019-08-07 14:41:27

标签: javascript audio

我试图在React中实现一个带有一些声音的按钮,但是我得到的却是:'TypeError: audio.play is not a function'

我试图创建元素并通过id来获取它,以及尝试将纯js与new Audio(src)一起使用。 在这两种情况下,我都会出错。 我在网上检查了数百个示例,它们都以相同的方式进行操作,但是不知为何我的方法不起作用

import React, { Component } from "react";
import { CSSTransition } from "react-transition-group";
import OctagonalButton from "./OctagonalButton";
import  "../../css/buttons/HeroButtons.css";
// import soundfile from "../../internalAsset/sounds/button-1.mp3";
class HeroButtons extends Component {
  constructor(props) {
    super(props);
    this.state = { fadeIn: false, hover: false };
  }

  componentDidMount() {
    this.setState({ fadeIn: true });
    // we add the even listener to buttons
    setTimeout(() => {
      // we add the even listener to buttons
      var button1 = document.querySelector("#HerofindMore1");
      button1.addEventListener("mouseenter", () => {
        this.toggleHover();
      });
      button1.addEventListener("mouseleave", () => {
        this.toggleHover();
      });
      var button2 = document.querySelector("#HerofindMore2");
      button2.addEventListener("mouseenter", () => {
        this.toggleHover();
      });
      button2.addEventListener("mouseleave", () => {
        this.toggleHover();
      });
    }, 600);
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.hover !== this.state.hover) {
      if (this.state.hover) {
        // on onMouseEnter we play the Sund
        this.Sound("play");
      } else {
        // if onMouseLeave we stop the sound
        this.Sound("stop");
      }
    }
  }

  handleClick = () => {
    // send the unmounting notification to hero header
    this.props.alertHeroHeader();
    // let the transition do its job before unmount the component
    this.setState({ fadeIn: false });
    // unmount the component
    setTimeout(() => {
      this.props.onClick();
    }, 2000);
  };

  toggleHover = () => {
    this.setState({ hover: !this.state.hover });
  };

  Sound = value => {

    let audio = new Audio("../../internalAsset/sounds/button-1.mp3");

    if (value === "play") {
      console.log("Play");
      console.log(audio);
       audio.play();
    } else {
      audio.pause();
      console.log("Stop");
    }
  };

  render() {
    return (
      <div>        
        <CSSTransition
          in={this.state.fadeIn}
          timeout={{ enter: 500, exit: 500 }}
          classNames={{
            appear: "fade-appear",
            appearActive: "fade-active-appear",
            enter: "fade-enter",
            enterActive: "fade-enter-active",
            enterDone: "fade-enter-done",
            exit: "fade-exit",
            exitActive: "fade-exit-active",
            exitDone: "fade-exit-done"
          }}
          unmountOnExit
          onExited={() => {
            this.props.onClick();
          }}
        >
          <div className="buttonHeroWrapper">
            <OctagonalButton
              type="HeroButtonMore1"
              id="HerofindMore1"
              onClick={this.handleClick}
            />
            <OctagonalButton
              type="HeroButtonMore2"
              id="HerofindMore2"
              onClick={this.handleClick}
            />
          </div>
        </CSSTransition>
      </div>
    );
  }
}
export default HeroButtons;

这是音频的console.log()

Audio {name: "audio", uuid: "9B72D3F7-2A6E-459D-A144-285ABACE1B9A", type: "Audio", format: "arraybuffer", encoding: "mp3", …}
data: ArrayBuffer(1862) {}
encoding: "mp3"
format: "arraybuffer"
name: "audio"
type: "Audio"
uuid: "9B72D3F7-2A6E-459D-A144-285ABACE1B9A"
__proto__: Resource

预先感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我建议在按钮组件上使用onMouseEnteronMouseLeave道具,那么您不需要在componentDidMount上附加事件。

我刚刚创建了一个示例,您可以在这里https://codesandbox.io/s/react-mdn-audio-ffgox

但是,如果您想继续使用addEventListener,则需要将箭头功能更改为普通功能,因为this将不会引用HeroButtons类。尝试这样的事情:

button2.addEventListener("mouseleave", function() {
  this.toggleHover();
});

我鼓励您使用带有React钩子的无状态组件;)

答案 1 :(得分:0)

好的,即使我到目前为止没有得到任何帮助,我也解决了这个问题,我在这里与遇到问题的所有人分享。希望会有所帮助。

出于某种原因,我不太清楚,new Audio(src)在React中不是一个可行的选择,某种程度上play()作为pause()的功能不起作用。因此,如果像我一样遇到同样的情况,请制作一个在渲染中带有<audio>元素的组件。

<audio id="audio">
 <source src={src} type="audio/mp3" />
</audio>

您可以使用:播放(或暂停等)。

document.getElementById("audio").play();

因此,当您将鼠标悬停在您选择的元素上时,我在这里创建的react组件将播放声音,只需在props中传递其css选择器数组即可:

import React, { Component } from "react";

import soundfile from "../../internalAsset/sounds/button-1.mp3";

class ButtonAudioPlayer extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  componentDidMount() {
    // we add the even listener to buttons

    this.props.buttonsSelectors.forEach(selector => {
      var button1 = document.querySelector(selector);
      button1.addEventListener("mouseenter", () => {
        this.sound("play");
      });
      button1.addEventListener("mouseleave", () => {
        this.sound("stop");
      });
    });
  }

  sound = value => {
    const track = document.getElementById("audio");
    if (value === "play") {
      track.load();
      track.play();
    } else {
      track.pause();
    }
  };

  render() {
    return (
      <audio id="audio">
        <source src={soundfile} type="audio/mp3" />
      </audio>
    );
  }
}
export default ButtonAudioPlayer;

希望这对您有所帮助:)