質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
jQueryプラグイン

jQueryの拡張機能。 様々な種類があり、その数は膨大です。公開済みのプラグインの他にも、自作することもできます。 jQueryで利用できるようにしておくだけで、導入およびカスタマイズが比較的容易に行なえます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

4回答

6404閲覧

jQuery「audiojs」で再生リストを複数設置したい

abell

総合スコア12

jQueryプラグイン

jQueryの拡張機能。 様々な種類があり、その数は膨大です。公開済みのプラグインの他にも、自作することもできます。 jQueryで利用できるようにしておくだけで、導入およびカスタマイズが比較的容易に行なえます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2015/06/11 05:41

audio.jsというjQueryのプラグインを使って、複数の再生リストを設置したいです。
(audio.js⇒ http://kolber.github.io/audiojs/)

上記のページのExample5が同一ページ内に複数あるイメージです。
こちらのサンプルを参考に、audio.jsを設置し、htmlのhead内には以下のようなスクリプトを記述しています。

lang

1 $(function() { 2 // Setup the player to autoplay the next track 3 var a = audiojs.createAll({ 4 trackEnded: function() { 5 var next = $('ol li.playing').next(); 6 if (!next.length) next = $('ol li').first(); 7 next.addClass('playing').siblings().removeClass('playing'); 8 audio.load($('a', next).attr('data-src')); 9 audio.play(); 10 } 11 }); 12 13 // Load in the first track 14 var audio = a[0]; 15 first = $('ol a').attr('data-src'); 16 $('ol li').first().addClass('playing'); 17 audio.load(first); 18 19 // Load in a track on click 20 $('ol li').click(function(e) { 21 e.preventDefault(); 22 $(this).addClass('playing').siblings().removeClass('playing'); 23 audio.load($('a', this).attr('data-src')); 24 audio.play(); 25 }); 26 // Keyboard shortcuts 27 $(document).keydown(function(e) { 28 var unicode = e.charCode ? e.charCode : e.keyCode; 29 // right arrow 30 if (unicode == 39) { 31 var next = $('ol li.playing').next(); 32 if (!next.length) next = $('ol li').first(); 33 next.click(); 34 // back arrow 35 } else if (unicode == 37) { 36 var prev = $('ol li.playing').prev(); 37 if (!prev.length) prev = $('ol li').last(); 38 prev.click(); 39 // spacebar 40 } else if (unicode == 32) { 41 audio.playPause(); 42 } 43 }) 44 });

また、body内は以下のようになっています。

lang

1<div id="audio_1"> 2 <p>Sample</p> 3 <audio preload="none"></audio> 4 <div class="list"> 5 <ol> 6 <li><a href="#" data-src="audio/sample1.mp3">sample1</a></li> 7 <li><a href="#" data-src="audio/sample2.mp3">sample2</a></li> 8 <li><a href="#" data-src="audio/sample3.mp3">sample3</a></li> 9 </ol> 10 </div> 11</div> 12<div id="audio_2"> 13 <p>Sample</p> 14 <audio preload="none"></audio> 15 <div class="list"> 16 <ol> 17 <li><a href="#" data-src="audio/sample4.mp3">sample4</a></li> 18 <li><a href="#" data-src="audio/sample5.mp3">sample5</a></li> 19 <li><a href="#" data-src="audio/sample6.mp3">sample6</a></li> 20 </ol> 21 </div> 22</div>

こちらを実行した結果、audio_2のsample4をクリックすると、audio_1のオーディオで再生され、audio_2のオーディオは動きませんでした。
sample1〜3は、audio_1で再生されました。

audio.jsの読み込み時にaudio要素が<div id="audio_wrapper#(Noが連番で入る)"で囲まれ、CSSでデザインされたプレイヤーが作られるのですが、audio_1はaudio_wrapper0、audio_2はaudio_wrapper1が振られています。
このうちのaudio_wrapper0でしか再生ができないようだったので、idを置き換えるスクリプトを作ってみたり、クラスで割り振るスクリプトを書いてみたりしたのですが、うまくいきませんでした。

jQuery含め、あまりプログラミングの知識がなく恐縮ですが、アドバイスいただけるとうれしいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

少しだけ用語の使い方が間違っていますが(例えば、var audio = audioList[index]; というコードは、「audioList配列のindex番目の要素をaudio変数に代入」を表しています。audioListに代入しているわけではありません)、認識は合っているので話を進めます。

再生中のものにplayingというclass属性値を付与するというアイデアは間違っていませんし、その方向性でもいずれは正しく実装できると思います。しかし、今回の場合だと、もっとシンプルに解決する手段が存在します。

まず、今回行いたい実装を文書化します。今回行いたいことは、「a要素をクリックしたときに、すべてのオーディオを停止し、クリックした音楽を再生する」です。「a要素をクリックしたとき」と「クリックした音楽を再生する」はもうすでに実装済みですので、これから実装するのは「すべてのオーディオを停止」の部分となります。つまり、下の/* ここにコードを追加する */の部分に、すべてのオーディオを停止する処理を書けばいいことになります。

lang

1$(function() { 2 var audioList = audiojs.createAll(); 3 4 $(".audio_box ol li a").on("click", function(e) { 5 e.preventDefault(); 6 7 /* ここにコードを追加する */ 8 9 var mybox = $(this).closest(".audio_box"); 10 var index = $(".audio_box").index(mybox); 11 12 var audio = audioList[index]; 13 audio.load($(this).data('src')); 14 audio.play(); 15 }); 16});

すべてのオーディオを停止するためには、まず「すべてのオーディオ」を取得する必要があります。しかし、新たに取得する必要はありません。なぜなら、audioList変数に、既に「すべてのオーディオ」が格納されているからです。audioList変数の中身をconsole.logで確認してみましょう。

lang

1[ 2 Object { element=audio, wrapper=div#audiojs_wrapper0, ... }, 3 Object { element=audio, wrapper=div#audiojs_wrapper1, ... } 4]

複数のオブジェクトが入っている配列であることがわかります。各オブジェクトが「オーディオ」を表します。
次に、オーディオの操作方法を調べることになりますが、実は既にオーディオを操作しているところがあります。それは、再生のところです。

lang

1var audio = audioList[index]; 2audio.load($(this).data('src')); 3audio.play();

audioList配列のうちの一つを取得し、それをaudio変数に代入しています。そして、再生するために.play()メソッドを呼び出しています。「再生するためのメソッドが用意されているのだから、停止するためのメソッドも用意されているはず」という予測が立てられます。そして、案の定停止するためのメソッドが存在します。abellさんも気づいておられますが、.pause()メソッドです。

さて、再生するためのコードを載せましたが、停止するためのコードは、再生するためのコードをほんの少し書き換えるだけでできます。次のコードです。

lang

1var audio = audioList[index]; 2audio.pause();

このコードは、オーディオの一つを停止するためのコードです。

ここまでで実装できたものは、「すべてのオーディオを取得する」と「一つのオーディオを停止する」です。この2つの実装を組み合わせることで、「すべてのオーディオを停止する」ことができます。JavaScriptの配列を扱えるようになることで、この2つを組み合わせることができます。
配列の扱い方は、今思いつくところで2つありますが、どちらも3行程度のシンプルなコードです。その3行のコードを/* ここにコードを追加する */の部分に追加することで、期待通りの動作を得られるかと思います。

投稿2015/06/12 11:50

anaprestoo

総合スコア199

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abell

2015/06/15 05:42

詳しいご説明ありがとうございます。 こうして文字にすると理解ができるのですが、自分で書こうとするとうまく行きません…。 色々と調べてみて、each関数が使えそうだったので、あとは最初のaudioListで取得された全てのオーディオは停止するだけ、と思い以下のようなコードを書きました。 $(this).each(function() { audio.pause(); }); なのですが、「TypeError: audio is undefined」というエラーが出てしまい…。 audioが定義されているのは確かにこの記述の後なので、audio.pause()をする前にaudioを定義すればいいのかと思い、var audio = audioList、var audio = []、など色々試してみたのですが、「TypeError: audio.pause is not a function」というエラーが…。 ここまでの考え方でどこか間違っているところはあるのでしょうか…。
anaprestoo

2015/06/15 07:23

考え方は合っていますし、each関数が使えるという発想も正しいです。ただ、使い方が間違っています。というのも、jQueryのeach関数の使い方は2通りあり、質問者さんが使っておられるのは、間違ったほうだからです。正しいほうの使い方は、以下のURLの記事に書かれています。 http://raining.bear-life.com/jquery/jquery%E3%81%A7%E9%85%8D%E5%88%97%E3%82%92%E3%83%AB%E3%83%BC%E3%83%97%E3%81%99%E3%82%8B%E3%80%8Ceach%E3%80%8D まずはこちらの記事に書かれたソースコードを丸々コピーして、手元のhtmlファイルにそのまま貼り付けます。そして、実際にブラウザでどのように表示されるかを確認し、そのあとで、少しだけソースコードに変更を加えていきます。「配列に"f"という要素を追加するとどのように表示が変わるか」や、「'<br>'という文字列を'-'に変えるとどうなるか」などを試します。そうやって少しずつコードの意味を理解していき、そのあとで本番環境(オーディオの操作)に埋め込みます。私はいつもそのようにしています。 答えが必要でしたら、いつでもおっしゃってください。
abell

2015/06/16 06:34

できました!下記のように記述してみたところ、一つのオーディオのみ再生されました。 var audio = audioList; $.each(audio, function(i, audio) { audio.pause(); }); function(i, audio)のiを使用していないのと、3行程度のはずが4行になってしまったので、無駄があるようにも思うのですが、もう少しすっきりさせることはできるのでしょうか? 何はともあれ、自力で答えが出せたことがとても嬉しいです。 長々とお付き合いくださって、本当にありがとうございます!
anaprestoo

2015/06/16 08:09

Arrayインスタンスの .forEach() メソッドを使うといいかと思います。 audioList.forEach(function(audio) { audio.pause(); }); iなどの使わない変数はひとつもなく、シンプルに書けています。 ちなみに、.each() や .forEach() などのメソッドを使わない方法もあります。 for (var i = 0; i < audioList.length; i++) { audioList[i].pause(); } どちらの方法でも書けるようになっておくといいと思います。
abell

2015/06/16 08:29

forEachの書き方はとてもシンプルで読みやすいですね。 こういった方法もあるのですね。とても勉強になります! 最初に行き詰まってから長い道のりでしたが、おかげさまで一つ一つ理解することができて、とても感謝しています。 引き続き、頑張りたいと思います。 本当にありがとうございました!
anaprestoo

2015/06/16 09:02

言い忘れましたが、この実装では「再生ボタンを押した時」に複数同時再生ができてしまいます。このバグを取り除いてみるのも面白いかもしれません。(このバグを取り除く過程で、JavaScriptのイベントについて理解できます)
abell

2015/06/17 08:33

anaprestooさんにご指摘いただくのと同じくらいで、自分でも気づいてしまいました。笑 理解を深めるためにも、もう少しJavascriptの勉強が進んだところでチャレンジしてみます!
guest

0

audioListの中身は何であるかを知ることにより、複数同時再生のバグは直せます。デバッグ頑張ってください!

投稿2015/06/12 01:54

anaprestoo

総合スコア199

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abell

2015/06/12 08:40

何をさせるために記述されているかまでは理解できるのですが、そこから先が進みません…。 書いてくださったものを順に見てみると、 var audioList = audiojs.createAll();  →audiojsのcreateAllを実行。(オーディオプレイヤーの作成) $(".audio_box ol li a").on("click", function(e) {  →liのaがクリックされたら、以下の処理を実行 e.preventDefault();  →aの<href>は実行せずに、親要素をバブリングする var mybox = $(this).closest(".audio_box");  →クリックされた要素の親要素にあたるクラス名audio_boxを探す var index = $(".audio_box").index(my box);  →my box変数で取得されたクラス名audio_boxを連番を振り当てる var audio = audioList[index];  →audioListにindex変数で取得した値を代入 audio.load($(this).data('src'));  →上記で取得されたaudioList[No]のsrcプロパティを読み込む audio.play();  →上記で取得されたaudioList[No]のsrcプロパティを再生 ということだと理解しています。 再生中のものにplayingというクラスを振って、子要素にplayingがない親要素はaudio.pauseすればいいのかと考えたのですが、そこで止まってしまい…。 至らないことばかりで申し訳ございませんが、アドバイスいただければと思います…。
guest

0

将来的に再生リストが増える可能性があるのでしたら、<div id="audio_1"><div id="audio_2">などの要素にclass属性を追加するほうがいいと思います。なぜならclass属性を追加しておくことで、再生リストが増えてもJavaScriptのコードを書き換える必要がなくなるからです。

例えば、再生リストの要素にclass="audio_box"を追加したとします。

lang

1<div id="audio_1" class="audio_box"> 2 <audio preload="none"></audio> 3 <ol> 4 <li><a href="#" data-src="audio/sample1.mp3">sample1</a></li> 5 <li><a href="#" data-src="audio/sample2.mp3">sample2</a></li> 6 <li><a href="#" data-src="audio/sample3.mp3">sample3</a></li> 7 </ol> 8</div> 9<div id="audio_2" class="audio_box"> 10 <audio preload="none"></audio> 11 <ol> 12 <li><a href="#" data-src="audio/sample4.mp3">sample4</a></li> 13 <li><a href="#" data-src="audio/sample5.mp3">sample5</a></li> 14 <li><a href="#" data-src="audio/sample6.mp3">sample6</a></li> 15 </ol> 16</div>

すると、JavaScriptのコードは次のように非常にシンプルになります。

lang

1$(function() { 2 var audioList = audiojs.createAll(); 3 4 $(".audio_box ol li a").on("click", function(e) { 5 e.preventDefault(); 6 7 var mybox = $(this).closest(".audio_box"); 8 var index = $(".audio_box").index(mybox); 9 10 var audio = audioList[index]; 11 audio.load($(this).data('src')); 12 audio.play(); 13 }); 14});

ここから、次のような再生リストを追加したとします。

lang

1<div class="audio_box"> 2 <audio preload="none"></audio> 3 <ol> 4 <li><a href="#" data-src="audio/sample7.mp3">sample7</a></li> 5 <li><a href="#" data-src="audio/sample8.mp3">sample8</a></li> 6 <li><a href="#" data-src="audio/sample9.mp3">sample9</a></li> 7 </ol> 8</div>

追加したからといって、JavaScriptのコードを書き換える必要はありません。なぜなら、再生リストの要素をclass属性で指定しているからです。id属性だけでは、JavaScriptのコードを書き換える必要が出てくるでしょう。

質問をするときは、コードをできるだけシンプルにしたほうがよいでしょう。例えば、今回の質問に、「keydownイベントの設定を行っているコード」は不要です。ということで、$(document).keydown(function(e) {...})の部分はまるごと削除できます。trackEndedの設定も不要でしょう。なぜなら、今回の質問と「再生が終えた時の処理」は無関係だからです。ということで、.createAll()の引数をなくします。残ったコードはこれだけです。

lang

1$(function() { 2 // Setup the player to autoplay the next track 3 var a = audiojs.createAll(); 4 5 // Load in the first track 6 var audio = a[0]; 7 first = $('ol a').attr('data-src'); 8 $('ol li').first().addClass('playing'); 9 audio.load(first); 10 11 // Load in a track on click 12 $('ol li').click(function(e) { 13 e.preventDefault(); 14 $(this).addClass('playing').siblings().removeClass('playing'); 15 audio.load($('a', this).attr('data-src')); 16 audio.play(); 17 }); 18});

このように、コードをシンプルにしていくことの利点は、回答者がコードの意味を理解しやすくなるだけでなく、質問者さん自身も、コードの意味をより深く理解できることです。私も、質問文を作成している過程で問題の本質が見えてくることがよくあります。ということで、質問者さんには、質問を投稿する前にコードの添削をすることをおすすめします(それは回答者にとっても喜ばしいことです)。

投稿2015/06/11 12:07

anaprestoo

総合スコア199

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abell

2015/06/12 01:44

アドバイスありがとうございます。 クラスでの管理の方がメンテナンスが簡単そうに思いましたので、こちらの方法でいきたいと思います。 書いてくださったソースを実行してみたところ、きちんと再生されました! なのですが、複数のプレイヤーが同時に再生されてしまったので、一つのみ再生するよう色々試しているところです…。 また、質問の仕方についてもとても参考になりました。 当初はパニックのようになってしまい、きちんと添削せずに質問をしてしまいましたが、改めて見直して、無駄な部分があったと気付くことができました。 今後気を付けたいと思います。ありがとうございます。
guest

0

var audio = a[0];
で#audio_1に固定されているのではないでしょうか?
上記を
var audio = a[1];
にすると#audio_2で再生されませんでしょうか?

もし、#audio_2で再生されるようでしたら#audio_1の中がクリックされたらa[0],
#audio_2ならa[1]を使用するようにすればいかがでしょうか。

投稿2015/06/11 07:28

packet1024

総合スコア342

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abell

2015/06/11 08:20

ご回答ありがとうございます。 ご指摘の通り、var audio = a[1]にしたところ、audio_2で再生されました! ここが固定値になっていたためにaudio_2で再生されなかったのですね…。 重ね重ねの質問になってしまい恐縮なのですが、クリックによって変数の値を入れ替えさせるのは、どのように記述をすればよいのでしょうか? $('#audio_1 ol li a').click(function(){ var audioo = a[0]; .......}); $('#audio_2 ol li a').click(function(){ var audioo = a[1]; .......}); のように単純に分けて書く、という感じでしょうか?
packet1024

2015/06/11 08:57

2つのプレイヤーは同時に再生させたいのでしょうか? それとも同時に再生することはなく、#audio_1再生中は#audio_2は停止? いずれにしましてもスクリプトを見直す必要があるかと思います。 とりあえず、liをクリックするところだけであれば $('ol li').click(function(e) { if ($(this).parents('#audio_1').size() == 1) { audio = a[0]; } else { audio = a[1]; } とすればいけるかもです。(テストしてません。エラー出ましたらすみません)
abell

2015/06/12 01:39

アドバイスありがとうございます。 プレイヤーは一つだけ再生させたいと思っています。 上記の方にアドバイスをいただいたクラスで管理する方法を試してみたところ、きちんと再生されたのですが、同時再生となってしまったので、一つだけ再生できるか試しているところです。 元々のソースのplayingというクラスの有無で実行できないかと思っているのですが、なかなかうまくいきません。 liがクリックされたらplayingクラスを付与、if文でplayingクラスがあったら再生させる処理を実行…という考え方でそもそも違っているのか、悩んでいるところです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問