首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在React中的音频标签中单击按钮时开始发出声音不起作用

在React中的音频标签中单击按钮时开始发出声音不起作用
EN

Stack Overflow用户
提问于 2019-02-03 22:57:46
回答 1查看 1.3K关注 0票数 0

我有一个主组件App,一个带有9个字母按钮的鼓,鼠标点击每个按钮就必须启动不同的声音文件。使用onClick事件和函数soundDetectionHandler,我可以检测哪个字母被按下了。当检测到时,我使用keyCode,keyTrigger,id,url将currentKey变量中的状态设置为该字母/对象。在子组件中,对于每个字母,我都有div,其中嵌入了音频标签,没有显示自己的控件。其中有一个按钮是onClick,它调用主组件中的audioActivationHandler函数,在检测到音频标签的类名的基础上开始播放声音文件(Url)。document.getElementsByClassName("player").play();不幸的是,它在鼠标点击时不起作用,有人可以检查一下,如果这不是最好的解决方案,有没有人提出更好的解决方案。下面是它的主要组件:

代码语言:javascript
复制
import React, { Component } from 'react';
import './App.css';
import Keypress from '.././components/Keypress/Keypress';

class App extends Component {
    constructor(props) {
        super(props)
        this.state = {
            currentKey: [],
                bankTwo : [{
                keyCode: 81,
                keyTrigger: 'Q',
                id: 'Chord-1',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3'
            }, {
                keyCode: 87,
                keyTrigger: 'W',
                id: 'Chord-2',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3'
            }, {
                keyCode: 69,
                keyTrigger: 'E',
                id: 'Chord-3',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3'
            }, {
                keyCode: 65,
                keyTrigger: 'A',
                id: 'Shaker',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Give_us_a_light.mp3'
            }, {
                keyCode: 83,
                keyTrigger: 'S',
                id: 'Open-HH',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3'
            }, {
                keyCode: 68,
                keyTrigger: 'D',
                id: 'Closed-HH',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3'
            }, {
                keyCode: 90,
                keyTrigger: 'Z',
                id: 'Punchy-Kick',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3'
            }, {
                keyCode: 88,
                keyTrigger: 'X',
                id: 'Side-Stick',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3'
            }, {
                keyCode: 67,
                keyTrigger: 'C',
                id: 'Snare',
                url: 'https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3'
            }],
            isChecked: false
        }
    }

    soundDetectionHandler = (event) => {
        let currentKey = this.state.bankTwo.filter((el, key) => {
            return el.id === event.target.id
        })

        this.setState ({
            currentKey: currentKey
        })
    }

    audioActivationHandler = () => {
        document.getElementsByClassName("player").play();

    }

    checkBoxHandler = () => {
        this.setState({
            isChecked: !this.state.isChecked
        })
    } 

    render () {
        const drum = this.state.bankTwo.map((keypress, key) => {
            return <Keypress
                key={keypress.keyCode}
                keypress={keypress}
                soundDetection={this.soundDetectionHandler}
                activated={this.audioActivationHandler}
            />
            }
        )
        return ( 
            <div className="App">
                <div className="container-fluid">
                    <div className="container">
                        <div className="DrumWrapper">
                            <div className="Drum">
                                {drum}
                            </div>
                            <div className="Controlls">
                                <label className="switch">
                                    <input type="checkbox"
                                        onChange={this.toggleChange}
                                    />
                                    <span className="slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>
                </div>     
            </div>
        )
    }
}
export default App;

下面是一个子无状态组件按键:

代码语言:javascript
复制
import React from 'react';

const keypress = (props) => {
    return (
        <div id={props.keypress.id} onClick={props.soundDetection}>
        {props.keypress.keyTrigger}
            <audio className="player" src={props.keypress.url}>
                <button onClick={props.activated}>Play</button>
            </audio>
        </div>
    );
}
export default keypress;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-04 10:40:23

这就是你要找的东西。我对你的代码进行了相当多的重构。我必须承认,在react think中完成这项工作有点让人费解。这里有一些评论。希望这能有所帮助:)

app.css:

代码语言:javascript
复制
.player {
  width:100px; 
  height: 100px;
  border: 1px solid black;
  color: black;
  display: flex;
  align-items: center; 
  justify-content:center;
  cursor: pointer;
  box-sizing: border-box;
}

player.js:

代码语言:javascript
复制
import React from 'react'
import './app.css'

export default class Player extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      active: false,
    }
    this.audio = React.createRef()
  }
  playAudio = () => {
    this.audio.current.play()
  }
  toggleActiveState = () => {
    this.setState({
      active: !this.state.active,
    })
  }
  render() {
    return (
      <div
        className="player"
        style={
          this.state.active
            ? {background: 'black', color: 'white'}
            : {backgroung: 'white', color: 'black'}
        }
        ref={this.ref}
        id={this.props.id}
        onClick={this.props.clicked}>
        <audio
          ref={this.audio}
          src={this.props.url}
          onEnded={this.toggleActiveState}
        />
        {this.props.keyTrigger}
      </div>
    )
  }
}

index.js:

代码语言:javascript
复制
import React from 'react'
import Player from './player'

const page = {
  width: '100vw',
  height: '100vh',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
}
const keyboard = {
  width: '300px',
  height: '300px',
  display: 'flex',
  flexWrap: 'wrap',
  alignItems: 'center',
  justifyContent: 'center',
  border: '1px solid black',
}

export default class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      currentKey: [],
      bankTwo: [
        {
          keyCode: 81,
          keyTrigger: 'Q',
          id: 'Chord-1',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3',
        },
        {
          keyCode: 87,
          keyTrigger: 'W',
          id: 'Chord-2',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3',
        },
        {
          keyCode: 69,
          keyTrigger: 'E',
          id: 'Chord-3',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3',
        },
        {
          keyCode: 65,
          keyTrigger: 'A',
          id: 'Shaker',
          url:
            'https://s3.amazonaws.com/freecodecamp/drums/Give_us_a_light.mp3',
        },
        {
          keyCode: 83,
          keyTrigger: 'S',
          id: 'Open-HH',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3',
        },
        {
          keyCode: 68,
          keyTrigger: 'D',
          id: 'Closed-HH',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3',
        },
        {
          keyCode: 90,
          keyTrigger: 'Z',
          id: 'Punchy-Kick',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3',
        },
        {
          keyCode: 88,
          keyTrigger: 'X',
          id: 'Side-Stick',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3',
        },
        {
          keyCode: 67,
          keyTrigger: 'C',
          id: 'Snare',
          url: 'https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3',
        },
      ],
      isChecked: false,
      bgColor: 'white',
    }
    this.handleKeyPress = this.handleKeyPress.bind(this)

    this.Q = React.createRef()
    this.W = React.createRef()
    this.E = React.createRef()
    this.A = React.createRef()
    this.D = React.createRef()
    this.S = React.createRef()
    this.Z = React.createRef()
    this.X = React.createRef()
    this.C = React.createRef()
  }

  componentDidMount() {
    document.addEventListener('keydown', this.handleKeyPress)
  }

  componentWillUnmount() {
    document.removeEventListener('keydown', this.handleKeyPress)
  }

  playAudioOnClick = e => {
    e.target.children[0].play()
    this[e.target.id].current.toggleActiveState()

  }

  handleKeyPress = e => {
    if (this.state.isChecked) {
      // in any case uppercase
      let which = e.key.toUpperCase()

      // check if the pressed key is defined as a keyTrigger in the state else do nothing
      if (
        this.state.bankTwo.some(key => {
          return key.keyTrigger === which
        })
      ) {
        // trigger functions in child
        this[which].current.playAudio()
        this[which].current.toggleActiveState()
      }
    }
  }
  handleCheck = () => {
    this.setState({
      isChecked: !this.state.isChecked,
    })
  }

  render() {
    const drum = this.state.bankTwo.map(player => {
      return (
        <Player
          id={player.keyTrigger}
          ref={this[player.keyTrigger]}
          key={player.keyCode}
          keyTrigger={player.keyTrigger}
          url={player.url}
          clicked={this.playAudioOnClick}
        />
      )
    })

    return (
      <section style={page}>
        <main style={keyboard}>{drum}</main>
        <section>
          <label>play with keyboard</label>
          <input type="checkbox" onChange={this.handleCheck} />
        </section>
      </section>
    )
  }
}

它通常是有效的,但玩得太快会使一些字段高亮显示,即使不是活动的。我希望看到一个更好的解决方案。不过,对于真正的乐器,我建议使用Web Audio API。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54504105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档