2017-06-06 22 views
0

我可以映射數組並渲染一些圖像(在generateWord函數底部附近)。我希望能夠點擊圖像,並播放相關的音頻文件。它播放陣列中的第二個(或最後一個)音頻文件。我想我應該在音頻文件中附加某種鍵或索引,以便知道要播放哪種音頻文件,但我不確定如何正確播放。下面的代碼是組件。部分狀態在它下面註釋,以便您可以看到映射數組的來源。在React應用中使用<audio>標籤,播放選定的文件onClick

const debug = require("debug")("components:Displayletter") 
const React = require("react") 
const { connect } = require("react-redux") 
const request = require("superagent") 
const { Link } = require("react-router") 

class Displayletter extends React.Component { 

    constructor() { 
    super() 
    this.playSound = this.playSound.bind(this) 
    } 

    playSound() { 
    this.playWord.play() 
    } 

    handleClick(e) { 
    e.preventDefault() 
    this.props.router.push("/") 
    } 

    render() { 
    debug(this.props) 
    const { dispatch, letters, letter } = this.props 
    const wordsArr = letter.wordImage 

    return (
     <div className="row letter-container"> 
     <div className="col-sm-12"> 
      {this.generateWord(wordsArr)} 
     </div> 
     </div> 
    ) 
    } 

    generateWord(wordsArr) { 
    return wordsArr.map((word) => { 
     return (
     <div> 
      <audio 
      key={word.sound} 
      ref={(x) => { this.playWord = x; }}> 
      <source src={word.sound} preload='auto'/> 
      </audio> 
      <img src={word.image} onClick={this.playSound} /> 
     </div> 
    ) 
    }) 
    } 
} 

module.exports = connect(state => state)(Displayletter) 

//STATE 
    // letters: [ 
    // { 
    //  id: 1, 
    //  capital: "A", 
    //  lowercase: "a", 
    //  capitalSound: "/sounds/capitalSounds/A.mp3", 
    //  lowerSound: "/sounds/lowerSounds/a.mp3", 
    //  wordImage: [ 
    //  {id:1, image:"images/words/aniwaniwa.png", sound: "sounds/ua.mp3"}, 
    //  {id:2, image:"images/words/anuhe.png", sound: "sounds/anuhe.mp3"}, 
    //  ], 
    //  multimedia: "/multimedia/aniwaniwa.webm", 
    //  mediaName: "Aniwaniwa Song", 
    // }, 

第二次迭代 - 增加了在構造一個空的對象,且穿過的onClick和playSound一個「字」的說法。

generateWord(wordsArr) { 
return wordsArr.map((word) => { 
    return (
    <div> 
    <audio 
     key={word} 
     ref={(x) => { this.playWords[word] = x; }}> 
      <source src={word.sound} preload='auto'/> 
    </audio> 
     <img src={word.image} onClick={this.playSound.bind(this, word)} /> 
    </div> 
) 
}) 

    playSound(word) { 
    this.playWords[word].play() 
    } 

    constructor() { 
    super() 
    this.playCapital = this.playCapital.bind(this) 
    this.playLower = this.playLower.bind(this) 
    this.playSound = this.playSound.bind(this) 
    this.playWords = {} 
    } 

***************第三輪*******************

const debug = require("debug")("components:Displayletter") 
const React = require("react") 
const { connect } = require("react-redux") 
const request = require("superagent") 
const { Link } = require("react-router") 

class Displayletter extends React.Component { 

    constructor() { 
    super() 
    this.playCapital = this.playCapital.bind(this) 
    this.playLower = this.playLower.bind(this) 
    this.playWords = {} 
    } 

    playCapital() { 
    this.playCap.play() 
    } 

    playLower() { 
    this.playLow.play() 
    } 

    playSound(word) { 
    this.playWords[word].play() 
    } 

    handleClick(e) { 
    e.preventDefault() 
    this.props.router.push("/") 
    } 



    render() { 
debug(this.props) 
const { dispatch, letters, letter } = this.props 
const wordsArr = letter.wordImage 

    return (
    <div className="row letter-container"> 
    <div className="col-sm-12"> 

     <audio 
     key={letter.capitalSound} 
     ref={(cap) => { this.playCap = cap; }}> 
     <source 
      src={letter.capitalSound} 
      preload="auto" /> 
     <track 
      kind="captions" 
      src="" 
      srcLang="en" /> 
     </audio> 

     <audio 
     key={letter.lowerSound} 
     ref={(low) => { this.playLow = low; }}> 
     <source 
      src={letter.lowerSound} 
      preload="auto" /> 
     <track 
      kind="captions" 
      src="" 
      srcLang="en" /> 
     </audio> 

     <button 
     type="button" 
     className="btn btn-xl display" 
     onClick={this.playCapital}> 
     {letter.capital} 
     </button> 

     <button 
     type="button" 
     className="btn btn-xl display" 
     onClick={this.playLower}> 
     {letter.lowercase} 
     </button> 

    </div> 

     <div className="col-sm-12"> 
    {this.generateWord(wordsArr)} 
    </div> 

     <div className="col-sm-12"> 
     <Link key={letter.id} to={`/media/${letter.capital}`}> 
     <button 
      type="button" 
      className="btn" 
      onClick={() => 
       dispatch({ 
       type: "RENDER_LETTER", 
       payload: letter, 
       }) 
      }> 
      Watch: {letter.mediaName} 
     </button> 
     </Link> 

    </div> 
    </div> 
) 
    } 

    generateWord(wordsArr) { 
    return wordsArr.map((word) => { 
     return (
    <div> 
      <audio 
     key={word} 
     ref={(x) => { this.playWords[word] = x; }}> 
      <source src={word.sound} preload='auto'/> 
      </audio> 
      <img src={word.image} onClick={this.playSound.bind(this, word)} /> 
     </div> 
    ) 
    }) 
    } 
} 

module.exports = connect(state => state)(Displayletter) 

    // letters: [ 
    // { 
    //  id: 1, 
    //  capital: "A", 
    //  lowercase: "a", 
    //  capitalSound: "/sounds/capitalSounds/A.mp3", 
    //  lowerSound: "/sounds/lowerSounds/a.mp3", 
    //  wordImage: [ 
    //  {id:1, image:"images/words/aniwaniwa.png", sound: "sounds/ua.mp3"}, 
    //  {id:2, image:"images/words/anuhe.png", sound: "sounds/anuhe.mp3"}, 
    //  ], 
    //  multimedia: "/multimedia/aniwaniwa.webm", 
    //  mediaName: "Aniwaniwa Song", 
    // }, 
+0

哪裏'sound'並且在對象定義'image'屬性? – guest271314

+0

在wordImage數組中的狀態 – janiet

+0

不知道javascript'問題是什麼問題?使用'reactjs'的經驗極少。您應該可以點擊''元素並開始音頻播放。 – guest271314

回答

1

你其實非常接近!問題在於如何保存對音頻元素的引用:ref={(x) => { this.playWord = x; }}。請注意,因爲它位於map,之間,因此每個元素都會一個接一個地保存爲this.playWord,因此爲什麼只有最後一個文件在點擊時才播放。

你想要做的是把所有的單詞保存到一個對象或數組,然後在你的點擊處理器中引用你想玩的那個。

首先,在您的構造函數中執行類似this.playWords = {}的操作,然後在render中執行ref={(x) => { this.playWords[word] = x; }}。這將爲您提供一個對象playWords,該對象存儲對按鍵輸入的所有音頻元素的引用。

然後,給playSound一個單詞參數,並確保onClick通過綁定該參數,如onClick={this.playSound.bind(this, word)}

我已經把一個簡單的例子說明了基本結構;您應該能夠輕鬆將這些原則應用於您的組件。

class Example extends React.Component { 
 
    constructor() { 
 
    super(); 
 
    this.words = {}; 
 
    } 
 

 
    logClick(i) { 
 
    console.log("user clicked on", this.words[i]); 
 
    } 
 

 
    render() { 
 
    const wordsArr = "this is an example sentence".split(" "); 
 
    return (
 
     <div className="row letter-container"> 
 
     <div className="col-sm-12"> 
 
      {this.generateWord(wordsArr)} 
 
     </div> 
 
     </div> 
 
    ) 
 
    } 
 

 
    generateWord(wordsArr) { 
 
    return wordsArr.map((word) => { 
 
     return (
 
     <div> 
 
      <span 
 
      key={word} 
 
      ref={x => { this.words[word] = x; }} 
 
      onClick={this.logClick.bind(this, word)} 
 
      > 
 
      {word} 
 
      </span> 
 
     </div> 
 
    ); 
 
    }) 
 
    } 
 
} 
 

 
ReactDOM.render(<Example />, document.getElementById("container"));
<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="container"/>

+0

嗨,感謝您的幫助 - 可以理解邏輯,但不知道我是否已經正確實施它,因爲它仍然不適合我,並且正在播放第二個聲音文件。在原始文章中添加了新代碼。 – janiet

+0

你綁定了'this.playSound'兩次;一次在構造函數中,再次在'render'中。嘗試只在'render'中綁定它 – Hamms

+0

從構造函數中刪除this.playSound,但仍然只是播放第二個聲音文件 – janiet

相關問題