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

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

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

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

HTML

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

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

1回答

1431閲覧

classListのエラー

toloveru83

総合スコア15

JavaScript

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

HTML

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

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2019/07/28 10:24

編集2019/07/28 11:53

前提・実現したいこと

HTMLとJavascriptで音階当てゲームを作っています。
現在、実装しようとしている機能は、クイズ開始時に問題の音に対しての
解答をクリック、又はキーボードで操作しようとしています。

発生している問題・エラーメッセージ

Google Chromeで動作確認を行っているのですが、鍵盤のキーボードをクリックしても音が鳴りません。 Chromeの検証ツールで確認したところ、下記エラーが表示されましたが、対処方法が分かりません。 Uncaught TypeError: Cannot read property 'classList' of null at OscillatorNode.checkNote(164行目) (追記) Oscillator[noteNo].connect(gain[notoNo])(64行目) notoNoをnoteNoに訂正。

該当のソースコード

HTML

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>音当てゲーム</title> 6<script> 7</script> 8</head> 9<body onload="init()"> 10<p>音当てゲーム</p> 11<input type="button" id="test" value="テスト" onclick="testGame()"> 12<input type="button" id="start" value="スタート" onclick="initGame()"> 13<input type="button" id="stop" value="ストップ" onclick="stop2Game()"> 14【第<span id="qNo">1</span>問:<span id="memo">白鍵のみ</span>】 15<span id="message"></span> 16<hr> 17volume:<input type="range" id="volume" value="0.5" min="0" max="1" 18step="0.1" onchange="setVolume()"> 19<span id="volumeText">[0.5]</span> 20 21<input type="button" value="ドレミを表示" onclick="showKeyboard(0)"> 22<input type="button" value="キーボードを表示" onclick="showKeyboard(1)"> 23<input type="button" value="表示を消す" onclick="clearKeyboard()"> 24<div id="piano"></div> 25</body> 26</html> 27

CSS

1<style> 2#piano {margin-top: 10px;} 3#piano div { 4 position: relative; 5 width: 80px; 6 height: 400px; 7 float: left; 8} 9#piano button {position: absolute;} 10.white{ 11 background-color: white; 12 top: 0px; 13 width: 80px; 14 height: 400px; 15 border-radius: 20px; 16 z-index: 0; 17} 18.black{ 19 background-color: black; 20 top: 0px; 21 left: 50px; 22 width: 60px; 23 height: 240px; 24 border-radius: 20px; 25 z-index: 1; 26} 27button div{ 28 position: absolute; 29 bottom: 0px; 30 left: 0px; 31 width: 100px; 32 font-size: 20px; 33} 34white div {color: black;} 35black div {color: gray;} 36.red{background-color: red;} 37.strike{background-color: yellow;} 38#memo {color: #0000CC;} 39#message {color: #CC0000;} 40</style>

JavaScript

1var audioContext = new AudioContext(); //オーディオコンテキスト 2var oscillator = new Array(); 3var gain = new Array(); 4var gainNode; //Gainノード 5var qNo,answer,cnt,total; //問題番号、解答、正解数 6var status; //ステータス(wait/qustion/answer) 7var startTime,timer1,timer2; 8var minNoteNo = 72; 9 10var doremi = ["ド","ド#","レ","レ#","ミ","ファ","ファ#","ソ","ソ#","ラ","ラ#","シ"]; 11 12var keyboard = ["Z","S","X","D","C","V","G","B","H","N","J","M"]; 13 14function init(){ 15 16for(var i=0;i<keyboard.length;i++){ 17 var noteNo; 18 19 noteNo = i+minNoteNo; 20 21var key = document.createElement("button"); 22key.id = "key_" + noteNo; 23key.onclick = touchKey; 24key.onclick = hitKey; 25key.onmousedown = mouseKeyDown; 26key.onmouseup = mouseKeyUp; 27key.onmouseleave = mouseKeyUp; 28 29if(doremi[noteNo%12].indexOf("#") > 0){ 30 //黒鍵 31 key.classList.add("black"); 32 }else{ 33 //白鍵 34 key.classList.add("white"); 35 var baseKey = document.createElement("div"); 36 } 37 //ベースの鍵盤に追加 38 baseKey.appendChild(key); 39 //ベースの鍵盤をピアノに追加 40 document.getElementById("piano").appendChild(baseKey); 41 } 42 43 //Gainノードの作成 44 gainNode = audioContext.createGain(); 45 setVolume(); 46} 47 48function touchKey(event){ 49 var noteNo = Number(event.target.id.split("_")[1]) + 72; 50 event.target.classList.add("yellow"); 51 //音階をセット 52 sound(noteNo); 53} 54 55function sound(noteNo){ 56 document.getElementById("test").disabled = true; 57 58var f = 440 * Math.pow(2,(noteNo-69) / 12); 59 60 oscillator[noteNo] = audioContext.createOscillator(); 61 gain[noteNo] = audioContext.createGain(); 62 63 //接続 64 oscillator[noteNo].connect(gain[noteNo]); 65 gain[noteNo].connect(audioContext.destination); 66 67 //周波数、ボリューム(無音)をセット 68 oscillator[noteNo].frequency.value = f; 69 gain[noteNo].gain.value = 0; 70 71 //無音で鳴らす 72 oscillator[noteNo].start(0); 73 } 74 75 function mouseKeyDown(event){ 76 //鍵盤のノートナンバー(4文字目以降の文字列)を取得 77 var noteNo = event.target.id.substr(4); 78 //音を鳴らす 79 playKey(noteNo); 80 } 81 82 function mouseKeyUp(event){ 83 //鍵盤のノートナンバー(4文字目以降の文字列)を取得 84 var noteNo = event.target.id.substr(4); 85 //音を止める 86 stopKey(noteNo); 87 } 88 89 document.onkeydown = function(event){ 90 //キーに割り当てられているショートカットをキャンセル 91 event.preventDefault(); 92 //押されたキーボードと対応する音を鳴らす 93 for(var i=0;i<keyboard.length;i++){ 94 if(event.key == keyboard[i].toLowerCase()) playKey(i+minNoteNo); 95 } 96 } 97 98 document.onkeyup = function(event){ 99 //放されたキーボードと対応する音を止める 100 for(var i=0;i<keyboard.length;i++){ 101 if(event.key == keyboard[i].toLowerCase()) stopKey(i+minNoteNo); 102 } 103 } 104 105 function playKey(noteNo){ 106 //音を鳴らす(ボリュームを上げる) 107 gain.value = document.getElementById("volume").value; 108 //押されている鍵盤にstrikeクラスを追加 109 document.getElementById("key_" + noteNo).classList.add("strike"); 110 } 111 112 function stopKey(noteNo){ 113 //無音にする 114 gain.value = 0; 115 //放された鍵盤からstrikeクラスを削除 116 document.getElementById("key_" + noteNo).classList.remove("strike"); 117 } 118 119function hitKey(event){ 120 if(status == "question"){ 121 //解答 122 cnt++; 123 status = "answer"; 124 //音階の生成 125 var noteNo = Number(event.target.id.split("_")[1]) + 72; 126 event.target.classList.add("red"); 127 //音階をセット 128 sound(noteNo); 129 } 130} 131 132function sound(noteNo){ 133 //oscillatorノードの作成 134 var oscillatorNode = audioContext.createOscillator(); 135 var f = 440 * Math.pow(2,(noteNo-69) / 12); 136 oscillatorNode.frequency.setValueAtTime(f,audioContext.currentTime); 137 //ノードの接続 138 oscillatorNode.connect(gainNode); 139 gainNode.connect(audioContext.destination); 140 //0.2秒間再生 141 oscillatorNode.start(audioContext.currentTime); 142 oscillatorNode.stop(audioContext.currentTime + 0.2); 143 if(status == "answer")oscillatorNode.onended = checkNote; 144} 145 146function setVolume(){ 147 //ボリュームをセット 148 var volume = document.getElementById("volume").value; 149 gainNode.gain.setValueAtTime(volume,audioContext.currentTime); 150 document.getElementById("volumeText").innerHTML = "[" + volume + "]"; 151} 152 153function checkNote(){ 154 //解答チェック 155 var message,key; 156 for(var noteNo=0;noteNo<doremi.length;noteNo++){ 157 key = document.getElementById("key_" + noteNo); 158 if(key.classList.contains("red")){ 159 if(key.id.split("_")[1] == answer){ 160 message = "正解![" + doremi[answer] + "]"; 161 if(cnt == 1)total++; 162 //5秒後に次の問題を表示 163 timer2 = setTimeout(function(){ 164 qNo++; 165 //次の問題/終了 166 if(qNo < 11){ 167 startGame(); 168 }else{ 169 stopGame(); 170 } 171 },5000); 172 }else{ 173 message = "不正解!!"; 174 status = "question"; 175 } 176 key.classList.remove("red"); 177 document.getElementById("message").innerText = message; 178 } 179 } 180} 181 182function testGame(){ 183 //開始 184 var 185 cnt = 0; 186 for(var i=0;i<doremi.length;i++){ 187 key = document.getElementById("key_" + noteNo); 188 document.getElementById("test").disabled = true; 189} 190} 191 192function initGame(){ 193 //初期化 194 total = 0; 195 qNo = 1; 196 //開始 197 document.getElementById("start").disabled = true; 198 startGame(); 199} 200 201function startGame(){ 202 //開始 203 cnt = 0; 204 status = "wait"; 205 document.getElementById("qNo").innerText = qNo; 206 document.getElementById("memo").innerText = "白鍵のみ"; 207 if(qNo > 5){ 208 document.getElementById("memo").innerText = "白鍵+黒鍵"; 209 } 210 startTime = Date.now(); 211 timer1 = setInterval(countTime,100); 212} 213 214function stop2Game(){ 215 //終了 216 status = "wait"; 217 var message = "終了 (正解数:" + total + "/" + qNo + ")" 218 document.getElementById("message").innerText = message; 219 document.getElementById("start").disabled = false; 220} 221 222function stopGame(){ 223 //終了 224 status = "wait"; 225 var message = "終了 (正解数:" + total + "/10)" 226 document.getElementById("message").innerText = message; 227 document.getElementById("start").disabled = false; 228} 229 230function countTime(){ 231 //カウントダウン 232 var time = 3 - Math.floor((Date.now() - startTime)/1000); 233 document.getElementById("message").innerHTML = "<b>" + time + "</b>"; 234 //問題 235 if(time == 0){ 236 status = "question"; 237 clearInterval(timer1); 238 document.getElementById("message").innerText = ""; 239 answer = Math.floor(Math.random() * 12); 240 //白鍵のみ調整 241 if((qNo < 6)&&(doremi[answer].indexOf("#") > 0)) answer++; 242 sound(answer + 72); 243 } 244} 245 246function showKeyboard(n){ 247 var noteNo,keyText; 248 for(var i=0;i<keyboard.length;i++){ 249 noteNo = i+minNoteNo; 250 if(n == 0){ 251 keyText = "<div id='text"+noteNo+"'>"+doremi[noteNo%12]+"</div>"; 252 }else{ 253 keyText = "<div id='text"+noteNo+"'>"+keyboard[i]+"</div>"; 254 } 255 document.getElementById("key_" + noteNo).innerHTML = keyText; 256 } 257} 258function clearKeyboard(){ 259 260 for(var i=0;i<keyboard.length;i++){ 261 document.getElementById("key_" + (i+minNoteNo)).innerHTML = ""; 262 } 263}

試したこと

エラーの該当箇所「 if(key.classList.contains("red")){」
JavaScript(158行目)から変数のスペルミス等確認していますがよくわかりません。
また、Oscillatorノードの周波数が規定値を超えている注意が出ていたため、
計算ミス等も探しましたが分かりませんでした。

補足情報(FW/ツールのバージョンなど)

Google Chrome最新バージョン:75.0.3770.142(Official Build) (64 ビット)

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

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

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

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

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

kei344

2019/07/28 11:39

回答が付いた質問の編集は慎重に行ってください。質問文のコードについて回答にて指摘があった場合は「追記」し、元のコードを編集する場合も「直したこと」がわかるようにしてください。後から見た人から見て、現在回答されておられる方の回答が「無いコードに対しての指摘」になり、意味がわからなくなります。
guest

回答1

0

noteNonotoNo担っている箇所が
複数箇所あります。

投稿2019/07/28 11:05

yasutomi

総合スコア2937

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

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

toloveru83

2019/07/28 11:14

ご回答ありがとうございます。 修正しましたが、エラーは解決しませんでした。
yasutomi

2019/07/28 11:16

ほかにも間違っている箇所があります。 確認が甘いので、もう一度よく見直してみてください。
toloveru83

2019/07/28 11:37

確認したところ、Oscillatorノードの接続部分にありましたので 修正しました。 エラーは変わらず出ているのですが、いかがでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問