在React中播放声音

时间:2018-09-30 13:38:56

标签: javascript reactjs audio

如何通过音频播放声音on单击React中的父元素。我不确定什么是正确的方法。有人建议我使用裁判,但是以什么方式?放在哪里?在div上包含音频标签还是音频标签本身?但是当我单击时,我单击div,而不是音频标签。那么当您单击音频的父级时,如何播放音频中的声音? 这是我的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './style.css';

class DrumMachine  extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            pressedKey: null,
            display: null,
            sliderVal: 50,
            volume: 0.5,
            mySwitch: true,
            mySwitchBox: true,
            prevVolume:  0.5,
            fancy: false,
        };
        this.handleClick = this.handleClick.bind(this);
        this.keyPress = this.keyPress.bind(this);
        this.handleVolume = this.handleVolume.bind(this);
        this.onOff = this.onOff.bind(this);
        this.fancyToggle = this.fancyToggle.bind(this);
        this.myRef = React.createRef();
        this.mySwitchOn = React.createRef();
        this.mySwitchOff = React.createRef();

        //Refs of audio elements.
        this.Q = React.createRef();
        this.W = React.createRef();
        this.E = React.createRef();
        this.A = React.createRef();
        this.S = React.createRef();
        this.D = React.createRef();
        this.Z = React.createRef();
        this.X = React.createRef();
        this.C = React.createRef();

        //Refs of divs who are parents of audio.
        this.H1 = React.createRef();
        this.H2 = React.createRef();
        this.H3 = React.createRef();
        this.H41 = React.createRef();
        this.H6 = React.createRef();
        this.Dsc_Oh = React.createRef();
        this.Kick_n_Hat = React.createRef();
        this.RP4_KICK_1 = React.createRef();
        this.Cev_H2 = React.createRef();

        this.myRange = React.createRef();

        this.sounds = {
            sound1: null,
            sound2: null,
            sound3: null,
            sound4: null,
            sound5: null,
            sound6: null,
            sound7: null,
            sound8: null,
            sound9: null
        };

        this.parents = {
            parent1: null,
            parent2: null,
            parent3: null,
            parent4: null,
            parent5: null,
            parent6: null,
            parent7: null,
            parent8: null,
            parent9: null
        };

        this.tracks = {
            track1: ["https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3", "https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3"],
            track2: ["https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Give_us_a_light.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3", "https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3"],
        };

        this.Id = {
            id1: ["Heater-1", "Heater-2", "Heater-3", "Heater-4", "Clap", "Open-HH", "Kick n' Hat", "Kick", "Closed-HH"],
            id2: ["Chord-1", "Chord-2", "Chord-3", "Shaker", "Open-HH", "Closed-HH", "Punchy-Kick", "Side-Stick", "Snare"],
        };

    }

    componentDidMount() {
        window.addEventListener("keydown", this.keyPress);

        this.sounds = {
            sound1: ReactDOM.findDOMNode(this.Q.current),
            sound2: ReactDOM.findDOMNode(this.W.current),
            sound3: ReactDOM.findDOMNode(this.E.current),
            sound4: ReactDOM.findDOMNode(this.A.current),
            sound5: ReactDOM.findDOMNode(this.S.current),
            sound6: ReactDOM.findDOMNode(this.D.current),
            sound7: ReactDOM.findDOMNode(this.Z.current),
            sound8: ReactDOM.findDOMNode(this.X.current),
            sound9: ReactDOM.findDOMNode(this.C.current)
        };

        this.parents = {
            parent1: ReactDOM.findDOMNode(this.H1.current),
            parent2: ReactDOM.findDOMNode(this.H2.current),
            parent3: ReactDOM.findDOMNode(this.H3.current),
            parent4: ReactDOM.findDOMNode(this.H41.current),
            parent5: ReactDOM.findDOMNode(this.H6.current),
            parent6: ReactDOM.findDOMNode(this.Dsc_Oh.current),
            parent7: ReactDOM.findDOMNode(this.Kick_n_Hat.current),
            parent8: ReactDOM.findDOMNode(this.RP4_KICK_1.current),
            parent9: ReactDOM.findDOMNode(this.Cev_H2.current)
        };
    }

    componentWillUnmount() {
        window.removeEventListener("keydown", this.keyPress);

        this.sounds = {
            sound1: ReactDOM.findDOMNode(this.Q.current),
            sound2: ReactDOM.findDOMNode(this.W.current),
            sound3: ReactDOM.findDOMNode(this.E.current),
            sound4: ReactDOM.findDOMNode(this.A.current),
            sound5: ReactDOM.findDOMNode(this.S.current),
            sound6: ReactDOM.findDOMNode(this.D.current),
            sound7: ReactDOM.findDOMNode(this.Z.current),
            sound8: ReactDOM.findDOMNode(this.X.current),
            sound9: ReactDOM.findDOMNode(this.C.current)
        };

        this.parents = {
            parent1: ReactDOM.findDOMNode(this.H1.current).id,
            parent2: ReactDOM.findDOMNode(this.H2.current).id,
            parent3: ReactDOM.findDOMNode(this.H3.current).id,
            parent4: ReactDOM.findDOMNode(this.H41.current).id,
            parent5: ReactDOM.findDOMNode(this.H6.current).id,
            parent6: ReactDOM.findDOMNode(this.Dsc_Oh.current).id,
            parent7: ReactDOM.findDOMNode(this.Kick_n_Hat.current).id,
            parent8: ReactDOM.findDOMNode(this.RP4_KICK_1.current).id,
            parent9: ReactDOM.findDOMNode(this.Cev_H2.current).id
        };
    }

    keyPress(event){

        let myKey = event.key;
        let displayId;

        switch (myKey.toUpperCase()) {
            case this.Q.current.id:
                this.sounds.sound1.volume = this.state.volume;
                this.sounds.sound1.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent1.id;
                }

                break;
            case this.W.current.id:
                this.sounds.sound2.volume = this.state.volume;
                this.sounds.sound2.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent2.id;
                }

                break;
            case this.E.current.id:
                this.sounds.sound3.volume = this.state.volume;
                this.sounds.sound3.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent3.id;
                }

                break;
            case this.A.current.id:
                this.sounds.sound4.volume = this.state.volume;
                this.sounds.sound4.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent4.id;
                }

                break;
            case this.S.current.id:
                this.sounds.sound5.volume = this.state.volume;
                this.sounds.sound5.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent5.id;
                }

                break;
            case this.D.current.id:
                this.sounds.sound6.volume = this.state.volume;
                this.sounds.sound6.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent6.id;
                }

                break;
            case this.Z.current.id:
                this.sounds.sound7.volume = this.state.volume;
                this.sounds.sound7.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent7.id;
                }

                break;
            case this.X.current.id:
                this.sounds.sound8.volume = this.state.volume;
                this.sounds.sound8.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent8.id;
                }

                break;
            case this.C.current.id:
                this.sounds.sound9.volume = this.state.volume;
                this.sounds.sound9.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent9.id;
                }

                break;
            default:

        }

        this.setState({
            display: displayId,
        });

    }

    handleClick(e){

        let displayId;

        switch (e.target.id) {
            case this.H1.current.id:
                this.sounds.sound1.volume = this.state.volume;
                this.sounds.sound1.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent1.id;
                }

                break;
            case this.H2.current.id:
                this.sounds.sound2.volume = this.state.volume;
                this.sounds.sound2.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent2.id;
                }

                break;
            case this.H3.current.id:
                this.sounds.sound3.volume = this.state.volume;
                this.sounds.sound3.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent3.id;
                }

                break;
            case this.H41.current.id:
                this.sounds.sound4.volume = this.state.volume;
                this.sounds.sound4.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent4.id;
                }

                break;
            case this.H6.current.id:
                this.sounds.sound5.volume = this.state.volume;
                this.sounds.sound5.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent5.id;
                }

                break;
            case this.Dsc_Oh.current.id:
                this.sounds.sound6.volume = this.state.volume;
                this.sounds.sound6.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent6.id;
                }

                break;
            case this.Kick_n_Hat.current.id:
                this.sounds.sound7.volume = this.state.volume;
                this.sounds.sound7.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent7.id;
                }

                break;
            case this.RP4_KICK_1.current.id:
                this.sounds.sound8.volume = this.state.volume;
                this.sounds.sound8.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent8.id;
                }

                break;
            case this.Cev_H2.current.id:
                this.sounds.sound9.volume = this.state.volume;
                this.sounds.sound9.play();

                if(this.state.volume===0){
                    displayId = null;
                }
                else{
                    displayId = this.parents.parent9.id;
                }

                break;
            default:

        }

        this.setState({
            display: displayId,
        });

    }

    handleVolume(e){

        this.setState({
            volume: e.target.value/100,
            sliderVal: e.target.value,
            prevVolume: e.target.value/100,
        });

    }

    onOff(e){

        if(this.state.mySwitch){
            this.setState({
                mySwitch: !this.state.mySwitch,
                mySwitchBox: !this.state.mySwitchBox,
                volume: 0,
            });
        }
        else{
            this.setState({
                mySwitch: !this.state.mySwitch,
                mySwitchBox: !this.state.mySwitchBox,
                volume: this.state.prevVolume,
            });
        }

    }


    fancyToggle(e){
        this.setState({
            fancy: e.target.checked
        });

    }

    render(){

        const displayId = this.state.display ? this.state.display : "No sound";
        const mySwitch = this.state.mySwitch ? "switchOn" : "switchOff";
        const mySwitchBox = this.state.mySwitchBox ? "switchBoxOn" : "switchBoxOff";
        const switchText = this.state.mySwitch ? "On" : "Off";
        const fancyId = this.state.fancy ? this.Id.id2.map(item2 => item2.replace("-"," ")) : this.Id.id1.map(item1 => item1.replace("-"," "));
        const track = this.state.fancy ? this.tracks.track2 : this.tracks.track1;

        console.log("***");
        console.log(fancyId);
        console.log(track);
        console.log("***");

        return(

            <div id="drum-machine" className="grid-container cent" ref={this.myRef}>
                <div id="display" className="item1">{displayId}</div>

                <div id={fancyId[0]} ref={this.H1} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    Q<audio id="Q" ref={this.Q} className="clip">
                        <source src={track[0]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[1]} ref={this.H2} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    W<audio id="W" ref={this.W} className="clip">
                        <source src={track[1]}></source>
                    </audio>
                </div>

                <div id={fancyId[2]} ref={this.H3} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    E<audio id="E" ref={this.E} className="clip">
                        <source src={track[2]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[3]} ref={this.H41} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    A<audio id="A" ref={this.A} className="clip">
                        <source src={track[3]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[4]} ref={this.H6} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    S<audio id="S" ref={this.S} className="clip">
                        <source src={track[4]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[5]} ref={this.Dsc_Oh} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    D<audio id="D" ref={this.D} className="clip">
                        <source src={track[5]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[6]} ref={this.Kick_n_Hat} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    Z<audio id="Z" ref={this.Z} className="clip">
                        <source src={track[6]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[7]} ref={this.RP4_KICK_1} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    X<audio id="X" ref={this.X} className="clip">
                        <source src={track[7]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div id={fancyId[8]} ref={this.Cev_H2} className="drum-pad btn btn-warning" onClick={this.handleClick}>
                    C<audio id="C" ref={this.C} className="clip">
                        <source src={track[8]} type="audio/mp3"></source>
                    </audio>
                </div>

                <div className="item3">
                    <input id="switch" type="checkbox" onChange={this.fancyToggle}/>
                    <div className="wrap">
                    <label htmlFor="switch"><span className="rib"></span><span className="rib"></span><span className="rib"></span></label>
                    </div>
                </div>

                <div className="item2">
                    <input type="range" min="1" max="100" value={this.state.sliderVal} className="slider" id="myRange" ref={this.myRange} onChange={this.handleVolume}/>
                    <div className="vol">Volume {this.state.sliderVal}</div>
                </div>

                <div id="sw"  className={mySwitchBox} onClick={this.onOff}>
                    <div className={mySwitch} ref={this.mySwitchOn}>{switchText}</div>
                </div>

            </div>

        );

    }

}

ReactDOM.render(<DrumMachine/>, document.getElementById('root'));

忽略注释掉的代码,有人对我说,这样做不是上帝的方式。另外,所说的代码是我已经尝试过的。这里正在工作example code.

更新的代码。现在,剩下要做的就是左下角的按钮,它可以在两个音轨集合之间交替显示。实际上,它可以实现预期的效果,但声音保持不变。在检查音频的源子标签后,我没有发现错误,也没有发现任何问题。它有适当的文件可以播放...令我感到困惑的是,这里的问题是什么,因为所有内容都符合规范...该按钮应该做什么:单击该按钮后,它应该更改包含音频元素的所有div ID,更改为render()中的fancyId变量中声明的值,也应该更改为render()中的变量轨道中声明的其他音频轨道。通过在许多地方使用console.log(),我无法查明问题出在哪里。我在单击按钮后检查了音频元素,然后更改了音频源。我跳来跳去,新的眼睛可以让我了解到我目前所处的这种不稳定状况。

Edit2:我想我找到了解决方案。而不是检查复选框是否例如在render()中按下(选中)了“按钮”,我在播放声音的方法(即handleClick()和keyPress())中检查了该状态(奇特)。因此,...如果为假,则使用一组声音,如果为假,则使用其他声音。检查codepen,它已更新。

1 个答案:

答案 0 :(得分:0)

首先,我将使用一个播放器而不是多个播放器,并将所有这些音频URL放入一个数组中,然后将它们作为文本链接列表循环放入render方法中。当用户单击链接时,我会通过状态用当前音频文件加载该播放器。像这样:

constructor () {
  super()
  this.state = {
    currentAudioFile: 0,
  }
  this.audiofiles = [
    {
      label: 'Heater-1',
      url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3'
    },
    {
      label: 'Heater-2',
      url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3'
    },
    ...
  ]
}

然后在render方法中:

render () {
  return (
    <div>
      <audio id="Player" controls>
        <source src={this.audiofiles[this.state.currentAudioFile].url} type="audio/mp3"></source>
      </audio>
      <ul>
        {
          this.audiofiles.map((item,i) => (
            <li>
              <span
                onClick={() => {
                  this.setState({
                    currentAudioFile: i,
                  })
                }}
              >
                {item.label}
              </span>
            </li>
          ))
        }
      </ul>
    </div>
  )
}

希望对您有帮助。