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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

1032閲覧

JavaScriptの二重再生を防止したい

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2021/09/08 11:00

編集2021/09/08 12:19

#前提・実現したいこと
私は、JavaScriptとHTMLの音楽再生をするページを作っています。
そこで、再生ボタンを何度も押せば、ずっと重なって音楽が再生できるということになってしまいます。
なので、それを防止すべく、変数による制御を加えてみたのですが、なぜか今まで通り再生できてしまいます。

#コード
JavaScriptとHTMLが混ざっています。

<!DOCTYPE HTML> <html> <head> <script> var music = new Audio('intro.mp3'); music.addEventListener("ended", function () { music.pause(); console.log('音楽終わり\nmusic2の再生!!'); music2(); }, false); function music2(){ var music2 = new Audio('naka1.mp3'); music2.play(); console.log('music2の再生'); music2.addEventListener("ended", function () { music2.pause(); console.log('音楽終わり\nmusic3の再生!!'); music3(); }, false); } function music3(){ var music3 = new Audio('naka2.mp3'); music3.play(); music3.addEventListener("ended", function () { music3.currentTime = 0; music3.play(); console.log('ループ中...'); }, false); } function start() { if (started == undefined){ var started; music.play(); console.log('[再生]'); var started = "abc"; }else{ aleat("再生中..."); } } //setTimeout(function(){ //music.pause(); //}, 30000); </script> <meta charset=UTF-8> <title>TEST</title> <body bgcolor=#bdbdbd> </head> <body> <center><button onclick="start()" style="padding:18px;">再生</button></center> </body> </html>

#試したこと
変数を使ってみる→なぜかできない。

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

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

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

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

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

Zuishin

2021/09/08 11:30

混ざってるのはいいけど、なぜインデントが無いんですか? 知恵袋かどこかからとってきたんですか?
mather

2021/09/08 11:32

ソースコードのインデントを付けましょう。
退会済みユーザー

退会済みユーザー

2021/09/08 12:15

すみません。 Windows 7付属のメモ帳を使ってのプログラミング、さらに自分がわかればいいやという思いから、インデントをつけていませんでした。 付け足しておきます。 また、このコードは自分で独自に作成していますので、どこの知恵袋にも載っていないと思います。 のっている場所といえば私のパソコンとこのページ、また、ここまでいく前の再生で詰まっていた時の以下のURLしかないと思います。 https://teratail.com/questions/356834
BeatStar

2021/09/08 13:09

次からはインデントを入れるように癖をつけた方がいいですよ。 それと、「知恵袋かどこから取ってきたのか」っていうのは、インデントの話もありそうですが、 多分、「自分で組んだのならわかるはず」という意味じゃないかなと。 つぎはぎでやっているのなら、意味を理解せずにやっていてもおかしくありませんが、 自分の頭で考えたのなら、できるはず……という意味かと。
guest

回答3

0

変数のスコープをきちんと認識しましょう。
started 変数を start 関数の外で宣言しないと意味がないですよ。

js

1function start() { 2 if (started == undefined) { // started はこれより前には宣言されてない 3 var started; // ここで初めて宣言されている 4 music.play(); 5 console.log("[再生]"); 6 var started = "abc"; // { ... } の内部でのみ有効なので、 if でいくら確認しても undefined のまま 7 } else { 8 aleat("再生中..."); // スペルミス 9 } 10}

投稿2021/09/08 11:40

mather

総合スコア6759

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

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

mather

2021/09/09 04:04

そうですね。言語仕様としてはその理解が正しいです。回答では嘘をついている部分があります。 しかし、やや複雑な仕様を理解する以前の問題だと思うので、まずは巻き上げを使わないように理解してもらったほうが良いと思いました。
guest

0

ベストアンサー

方法1: 単純にイベントを解除する

ここここを見ると
removeEventListenerを使って解除すばいいだけっぽいです。

方法2: 条件を付けて動かす

日本語で考えてみてください。(英語母語話者なら英語で、中国語母語話者なら中国語で……でもいいですが)

とにかく自分が解釈できる言語で単純に考えてみてください。

どういうときに動いて、どういうときに動きをキャンセルしますか?

どういうときに動いて -> 単純にボタンが押されたとき どういうときに(動きを)キャンセルするか -> ???

どういうときにキャンセルするか、つまり「動くときと動かない時の違い」を考えるのです。

そう、「すでに再生ボタンが押されたとき」とかのようなものですね。

まだ再生ボタンが押されていない状態と、押された後の状態の二つが出てきます。

ということは、「押されたときの挙動」で、「状態を変える」べきですね。

押す前と押した後の二つの状態を見ればいいのです。

2値なので true/falseでもいいですね。

たとえば isClicked 変数を用意して、デフォルトではfalseに。

そして、ボタンが押されたとかの処理のときに、isClicked を trueにする。

そうすれば、「ボタンが押された( isClicked == true ) でないなら、処理する」とかみたいな事ができますね。


[追記1]

なので、それを防止すべく、変数による制御を加えてみたのですが、なぜか今まで通り再生できてしまいます。

それはね。当たり前です。

コードを読んでみましょう。

コードを読むコツは『一行レベルで、何をしているかを考えながら読む』です。

とりま、読んでみましょう。

// 関数 startを定義 function start() { // started が undefined なら if (started == undefined){ // started 変数を宣言 var started; // 音楽を再生 music.play(); // 「[再生]」と表示 console.log('[再生]'); // started 変数を宣言し、"abc" をセット var started = "abc"; }else{ // それ以外 (=> startがundefined以外) ) なら      // 再生中 aleat("再生中..."); } }

そして、これを疑似コードとして書きだしてみましょう。

1. startedがundefinedなら 1.1. started変数を宣言 1.2. 音楽を再生 1.3. started変数を宣言し、"abc"をセット 2. それ以外なら 2.1. 再生中

この疑似コードを、現実世界で手作業でシミュレーションしてみてください。

つまり、ホワイトボードかなんかを用意して、

ホワイトボードにある started とあるものを読んでundefinedかどうかを調べる → (まだ無いようだ)=> (undefinedである) → started == undefinedは満たす → started という名前のものをホワイトボードに書く [started: ???] → 音楽を再生 → さらに別のところに started: abc と書く。 [started: ???] [started: abc] → また呼び出されたので startedがundifinedかどうか調べる → (適当なものを見る) → (undefinedだ) → startedを宣言 [started: ???] [started: abc] [started: ???] ...

のような感じでしょうか。

まあ、実際には最適化が行われると思いますが。

なんか、おかしくないですか?

(1)で調べているstartedはどこにあるのでしょうか。

で、仮にグローバル変数としてあるとしても、

(1.1) でさらにローカル変数としてstartedを宣言しています。

そうなると、次に(関数内で)startedにアクセスするときは ローカル変数にアクセスするはずです。
(関数から抜けた後なら別だろうけど)

つまり、(1) ≠ (1.1) です。

さらに (1.3)でstartedを宣言し、"abc"を入れています。

そうなると、別の変数として宣言しているはずです。
(ちなみに、C言語とかのような言語だとこの時点でエラー)

それに (1.1) ≠ (1.3) です。

おそらく、「別の変数として見なされている」可能性が高いです。

varを付けると、宣言で、「このブロックでしか使わないもの」という感じです。

投稿2021/09/08 11:22

編集2021/09/08 13:31
BeatStar

総合スコア4962

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

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

退会済みユーザー

退会済みユーザー

2021/09/09 09:52

ありがとうございます。ヒントをもとに試行錯誤した結果、自己解決できました。 本当にありがとうございました。
guest

0

BeatStarさんの助言を元に、以下のようにしたらできました。
最初に、started = false;と記述、
再生部分を以下のように変更

JavaScript

1function start() { 2 if (started == false){ 3 started = true; 4 music.play(); 5 console.log("[再生]"); 6 }else{ 7 alert("再生中..."); 8 } 9}

変数は前まで1種類しかないと思っていました。
変数について、また勉強します。

投稿2021/09/09 10:02

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問