【问题标题】:multiple <audio> tags playing different source files多个 <audio> 标签播放不同的源文件
【发布时间】:2017-05-15 09:08:32
【问题描述】:

我在页面上有几个按钮,单击时我希望播放特定的声音。它可以与一个标签一起使用,但是当我尝试添加另一个标签(使用不同的来源)时,它会跳到第二个标签并且不会播放第一个标签。

<audio ref={`${cap}`} >
     <source src={singleLetter.capitalSound} preload='auto'/>
     </audio>

 <audio ref={`${low}`} >
     <source src={singleLetter.lowerSound} preload='auto'/>
 </audio>

    <button type="button" className="btn btn-lg display"
    onClick={() =>
      this.playCapital(cap)
    }>
      {singleLetter.capital}
    </button>

    <button type="button" className="btn btn-lg display"
    onClick={() =>
      this.playLower(low)
    }>
      {singleLetter.lowercase}
    </button>

我还使用以下来播放声音(它是一个 react/redux 应用程序):

playCapital(cap) {
  this.refs[cap].load()
  this.refs[cap].play()
}

playLower(low) {
  this.refs[low].load()
  this.refs[low].play()
}

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    在将组件渲染到 DOM 时,React 重用节点,这可能会导致您所描述的问题(尤其是 &lt;audio&gt;&lt;video&gt; 标签)。如果你真的想使用 React 来播放声音,你必须探索不同的方法——分配键,将每个声音渲染为独立的组件,等等。

    您应该考虑使用HTML5 Audio API as shown here - 它会更清晰且不需要破解。

    下面是不同虚拟 dom 技术的示例 - 每种技术都有不同的效果。第一个示例将每个声音呈现为单独的音频标签,并通过 url 引用它们。这可能是你想要得到的:

    const sets = [
      {
          capital: 'Play WinXP error',
          capitalSound: 'https://www.myinstants.com/media/sounds/erro.mp3',
          
          lowercase: 'Play MSG',
          lowerSound: 'https://www.myinstants.com/media/sounds/metalgearsolid.swf.mp3'
       },
       
       {
          capital: 'Play Leeroy Jenking',
          capitalSound: 'https://www.myinstants.com/media/sounds/leroy.swf.mp3',
          
          lowercase: 'Play Murlock',
          lowerSound: 'https://www.myinstants.com/media/sounds/sound-9_____.mp3'
        }
    
    ]
    
    class Example extends React.Component {
      constructor() {
        super()
        
        this.state = {
          set: 0,
          sounds: [
            sets[0].capitalSound, 
            sets[0].lowerSound, 
          ]
        }
        
        this.playSound = this.playSound.bind(this)
      }
      
      playSound(sound) {
        this.refs[sound].load()
        this.refs[sound].play()
      }
    
      render() {
        const singleLetter = sets[this.state.set]
        
        return (
          <div>
            {this.state.sounds.map(sound => 
              <audio key={sound} ref={`${sound}`} >
                <source src={sound} preload='auto'/>
              </audio>
            )}
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playSound(singleLetter.capitalSound)
            }>
              {singleLetter.capital}
            </button>
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playSound(singleLetter.lowerSound)
            }>
              {singleLetter.lowercase}
            </button>
            
            <button onClick={() =>
              this.setState({
                sounds: this.state.set == 0 ? 
                  [
                    ...this.state.sounds,
                    sets[1].capitalSound, 
                    sets[1].lowerSound
                  ]
                  :
                  [
                    ...this.state.sounds,
                    sets[0].capitalSound, 
                    sets[0].lowerSound
                  ],
                set: this.state.set == 0 ? 1 : 0
              })
            }>
              Change set
            </button>
          </div>
        )
      }
    }
    
    ReactDOM.render(
      <Example />,
      document.getElementById("app")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="app"></div>

    没有按键的例子,相同的声音加载后会停止播放,当设置改变时播放。 (更改设置 -> 播放 Leeroy -> 更改设置 -> 播放 WinXP -- Leeroy 停止)

    const sets = [
      {
          capital: 'Play WinXP error',
          capitalSound: 'https://www.myinstants.com/media/sounds/erro.mp3',
          
          lowercase: 'Play MSG',
          lowerSound: 'https://www.myinstants.com/media/sounds/metalgearsolid.swf.mp3'
       },
       
       {
          capital: 'Play Leeroy Jenking',
          capitalSound: 'https://www.myinstants.com/media/sounds/leroy.swf.mp3',
          
          lowercase: 'Play Murlock',
          lowerSound: 'https://www.myinstants.com/media/sounds/sound-9_____.mp3'
        }
    
    ]
    
    class Example extends React.Component {
      constructor() {
        super()
        
        this.state = {set: 0}
        
        this.playCapital = this.playCapital.bind(this)
        this.playLower = this.playLower.bind(this)
      }
      
      playCapital(cap) {
        this.refs[cap].load()
        this.refs[cap].play()
      }
    
      playLower(low) {
        this.refs[low].load()
        this.refs[low].play()
      }
    
      render() {
        const cap = 'cap'
        const low = 'low'
        
        const singleLetter = sets[this.state.set]
        
        return (
          <div>
            <audio ref={`${cap}`} >
              <source src={singleLetter.capitalSound} preload='auto'/>
            </audio>
    
            <audio ref={`${low}`} >
              <source src={singleLetter.lowerSound} preload='auto'/>
            </audio>
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playCapital(cap)
            }>
              {singleLetter.capital}
            </button>
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playLower(low)
            }>
              {singleLetter.lowercase}
            </button>
            
            <button onClick={() =>
              this.setState({set: this.state.set == 0 ? 1 : 0})
            }>
              Change set
            </button>
          </div>
        )
      }
    }
    
    ReactDOM.render(
      <Example />,
      document.getElementById("app")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="app"></div>

    以键为例,当由于 React 考虑到这些标签不同并且不重用 &lt;audio&gt; 标签而导致集合发生更改时,声音立即停止。 (在播放声音时更改设置以观察音频标签被移除)

    const sets = [
      {
          capital: 'Play WinXP error',
          capitalSound: 'https://www.myinstants.com/media/sounds/erro.mp3',
          
          lowercase: 'Play MSG',
          lowerSound: 'https://www.myinstants.com/media/sounds/metalgearsolid.swf.mp3'
       },
       
       {
          capital: 'Play Leeroy Jenking',
          capitalSound: 'https://www.myinstants.com/media/sounds/leroy.swf.mp3',
          
          lowercase: 'Play Murlock',
          lowerSound: 'https://www.myinstants.com/media/sounds/sound-9_____.mp3'
        }
    
    ]
    
    class Example extends React.Component {
      constructor() {
        super()
        
        this.state = {set: 0}
        
        this.playCapital = this.playCapital.bind(this)
        this.playLower = this.playLower.bind(this)
      }
      
      playCapital(cap) {
        this.refs[cap].load()
        this.refs[cap].play()
      }
    
      playLower(low) {
        this.refs[low].load()
        this.refs[low].play()
      }
    
      render() {
        const cap = 'cap'
        const low = 'low'
        
        const singleLetter = sets[this.state.set]
        
        return (
          <div>
            <audio key={singleLetter.capitalSound} ref={`${cap}`} >
              <source src={singleLetter.capitalSound} preload='auto'/>
            </audio>
    
            <audio key={singleLetter.lowerSound} ref={`${low}`} >
              <source src={singleLetter.lowerSound} preload='auto'/>
            </audio>
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playCapital(cap)
            }>
              {singleLetter.capital}
            </button>
    
            <button type="button" className="btn btn-lg display"
            onClick={() =>
              this.playLower(low)
            }>
              {singleLetter.lowercase}
            </button>
            
            <button onClick={() =>
              this.setState({set: this.state.set == 0 ? 1 : 0})
            }>
              Change set
            </button>
          </div>
        )
      }
    }
    
    ReactDOM.render(
      <Example />,
      document.getElementById("app")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="app"></div>

    【讨论】:

    • 最后一个例子对我来说效果很好,非常感谢 Przemyslaw - 我使用了按键,我可以更好地理解如何将道具分别放入音频标签中。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多