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

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

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

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

HTML

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

Q&A

解決済

2回答

23313閲覧

classListのエラーについて

toloveru83

総合スコア15

JavaScript

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

HTML

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

0グッド

0クリップ

投稿2019/07/22 02:22

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
HTMLとJavascriptで音階当てゲームを作っています。
現在、実装しようとしている機能は、クイズ開始前に各音の確認をするために
クリック、又はキーボードで音を鳴らす仕組みです。

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

Google Chromeで動作確認を行っているのですが、鍵盤のキーボードをクリックしても音が鳴りません。 Chromeの検証ツールで確認したところ、下記エラーが表示されましたが、対処方法が分かりません。 Uncaught TypeError: Cannot read property 'classList' of null

該当のソースコード

Javascript

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>音当てゲーム</title> 6<script> 7var audioContext = new AudioContext(); 8var oscillator = new Array(); 9var gain = new Array(); 10var gainNode; 11var qNo,answer,cnt,total; 12var status; 13var startTime,timer1,timer2; 14var minNotoNo = 72; 15 16var doremi = ["ド","ド#","レ","レ#","ミ","ファ","ファ#","ソ","ソ#","ラ","ラ#","シ"]; 17 18var keyboard = ["Z","S","X","C","F","V","G","B","N","J","M","K"]; 19 20function init(){ 21 22for(var i=0;i<keyboard.length;i++){ 23 var notoNo; 24 25 notoNo = i+minNotoNo; 26 27var key = document.createElement("button"); 28key.id = "note" + notoNo; 29key.id = "key_" + i; 30key.onclick = hitKey; 31key.onmousedown = mouseKeyDown; 32key.onmouseup = mouseKeyUp; 33key.onmouseleave = mouseKeyUp; 34 35 36if(doremi[notoNo%12].indexOf("#") > 0){ 37 //黒鍵 38 key.classList.add("black"); 39 }else{ 40 //白鍵 41 key.classList.add("white"); 42 var baseKey = document.createElement("div"); 43 } 44 45 baseKey.appendChild(key); 46 47 document.getElementById("piano").appendChild(baseKey); 48 49 setSound(notoNo); 50 } 51 52 53 gainNode = audioContext.createGain(); 54 setVolume(); 55} 56 57function setSound(notoNo){ 58 59 var f = 440*Math.pow(2,(notoNo-69)/12); 60 61 oscillator[notoNo] = audioContext.createOscillator(); 62 gain[notoNo] = audioContext.createGain(); 63 64 65 oscillator[notoNo].connect(gain[notoNo]); 66 gain[notoNo].connect(audioContext.destination); 67 68 69 oscillator[notoNo].frequency.value = f; 70 gain[notoNo].gain.value = 0; 71 72 73 oscillator[notoNo].start(); 74 } 75 76 function mouseKeyDown(event){ 77 78 var notoNo = event.target.id.substr(4); 79 80 playKey(notoNo); 81 } 82 83 function mouseKeyUp(event){ 84 85 var notoNo = event.target.id.substr(4); 86 87 stopKey(notoNo); 88 } 89 90 document.onkeydown = function(event){ 91 92 event.preventDefault(); 93 94 for(var i=0;i<keyboard.length;i++){ 95 if(event.key == keyboard[i].toLowerCase()) playKey(i+minNotoNo); 96 } 97 }; 98 99 document.onkeyup = function(event){ 100 101 for(var i=0;i<keyboard.length;i++){ 102 if(event.key == keyboard[i].toLowerCase()) stopKey(i+minNotoNo); 103 } 104 }; 105 106 function playKey(notoNo){ 107 108 gain.value = document.getElementById("volume").value; 109 110 document.getElementById("note"+notoNo).classList.add("strike"); 111 } 112 113 function stopKey(notoNo){ 114 115 gain.value = 0; 116 117 document.getElementById("note"+notoNo).classList.remove("strike"); 118 } 119 120function hitKey(event){ 121 if(status == "question"){ 122 123 cnt++; 124 status = "answer"; 125 126 var noteNo = Number(event.target.id.split("_")[1]) + 72; 127 event.target.classList.add("red"); 128 129 sound(noteNo); 130 } 131} 132 133function sound(noteNo){ 134 //oscillatorノードの作成 135 var oscillatorNode = audioContext.createOscillator(); 136 var f = 440 * Math.pow(2,(noteNo-69) / 12); 137 oscillatorNode.frequency.setValueAtTime(f,audioContext.currentTime); 138 139 oscillatorNode.connect(gainNode); 140 gainNode.connect(audioContext.destination); 141 142 oscillatorNode.start(audioContext.currentTime); 143 oscillatorNode.stop(audioContext.currentTime + 0.2); 144 if(status == "answer")oscillatorNode.onended = checkNote; 145} 146 147function setVolume(){ 148 149 var volume = document.getElementById("volume").value; 150 gainNode.gain.setValueAtTime(volume,audioContext.currentTime); 151 document.getElementById("volumeText").innerHTML = "[" + volume + "]"; 152} 153 154 155 156function checkNote(){ 157 158 var message,key; 159 for(var i=0;i<doremi.length;i++){ 160 key = document.getElementById("key_" + i); 161 if(key.classList.contains("red")){ 162 if(key.id.split("_")[1] == answer){ 163 message = "正解![" + doremi[answer] + "]"; 164 if(cnt == 1)total++; 165 166 timer2 = setTimeout(function(){ 167 qNo++; 168 169 if(qNo < 11){ 170 startGame(); 171 }else{ 172 stopGame(); 173 } 174 },5000); 175 }else{ 176 message = "不正解!!"; 177 status = "question"; 178 } 179 key.classList.remove("red"); 180 document.getElementById("message").innerText = message; 181 } 182 } 183} 184 185function initGame(){ 186 187 total = 0; 188 qNo = 1; 189 190 document.getElementById("start").disabled = true; 191 startGame(); 192} 193 194function startGame(){ 195 196 cnt = 0; 197 status = "wait"; 198 document.getElementById("qNo").innerText = qNo; 199 document.getElementById("memo").innerText = "白鍵のみ"; 200 if(qNo > 5){ 201 document.getElementById("memo").innerText = "白鍵+黒鍵"; 202 } 203 startTime = Date.now(); 204 timer1 = setInterval(countTime,100); 205} 206 207function stop2Game(){ 208 209 status = "wait"; 210 var message = "終了 (正解数:" + total + "/" + qNo + ")" 211 document.getElementById("message").innerText = message; 212 document.getElementById("start").disabled = false; 213} 214 215function stopGame(){ 216 217 status = "wait"; 218 var message = "終了 (正解数:" + total + "/10)" 219 document.getElementById("message").innerText = message; 220 document.getElementById("start").disabled = false; 221} 222 223function countTime(){ 224 225 var time = 3 - Math.floor((Date.now() - startTime)/1000); 226 document.getElementById("message").innerHTML = "<b>" + time + "</b>"; 227 228 if(time == 0){ 229 status = "question"; 230 clearInterval(timer1); 231 document.getElementById("message").innerText = ""; 232 answer = Math.floor(Math.random() * 12); 233 234 if((qNo < 6)&&(doremi[answer].indexOf("#") > 0)) answer++; 235 sound(answer + 72); 236 } 237} 238 239function showKeyboard(){ 240 var noteNo,keyText; 241 for(var i=0;i<doremi.length;i++){ 242 noteNo = i+minNotoNo; 243 keyText = "<div id='text"+noteNo+"'>"+doremi[noteNo%12]+"</div>"; 244 document.getElementById("key_" + i).innerHTML = keyText; 245 } 246} 247</script> 248<style> 249#piano {margin-top: 10px;} 250#piano div { 251 position: relative; 252 width: 80px; 253 height: 400px; 254 float: left; 255} 256#piano button {position: absolute;} 257.white{ 258 background-color: white; 259 top: 0px; 260 width: 80px; 261 height: 400px; 262 border-radius: 20px; 263 z-index: 0; 264} 265.black{ 266 background-color: black; 267 top: 0px; 268 left: 50px; 269 width: 60px; 270 height: 240px; 271 border-radius: 20px; 272 z-index: 1; 273} 274button div{ 275 position: absolute; 276 bottom: 0px; 277 left: 0px; 278 width: 100px; 279 font-size: 20px; 280} 281white div {color: black;} 282black div {color: gray;} 283.red{background-color: red;} 284#memo {color: #0000CC;} 285#message {color: #CC0000;} 286</style> 287<body onload="init()"> 288<p>音当てゲーム</p> 289<input type="button" id="start" value="スタート" onclick="initGame()"> 290<input type="button" id="stop" value="ストップ" onclick="stop2Game()"> 291<input type="button" value="ドレミを表示" onclick="showKeyboard()"> 292【第<span id="qNo">1</span>問:<span id="memo">白鍵のみ</span>293<span id="message"></span> 294<hr> 295volume:<input type="range" id="volume" value="0.5" min="0" max="1" 296step="0.1" onchange="setVolume()"> 297<span id="volumeText">[0.5]</span> 298<div id="piano"></div> 299</body> 300</html> 301

試したこと

エラーの該当箇所「document.getElementById("note"+notoNo).classList.remove("strike");」
(117行目)から変数のスペルミス等確認していますがよくわかりません。

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

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

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

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

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

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

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

m.ts10806

2019/07/22 02:28

</head>がないのでHTML構文的にはNGです。 そこは修正されたほうが良いかと(構文チェックを自動でしてくれるエディタは使いたいですね)
toloveru83

2019/07/22 03:12

ご指摘ありがとうございます! エディタはAtomを使っているのですが、自動チェックのツール等ないか探してみようと思います! もしよろしければ、おすすめのエディタ等ありますしたら教えていただけると幸いです!
guest

回答2

0

エラーの直前行に

javascript

1console.log(document.getElementById("note"+notoNo));

としてみてください
nullだったり、notoNoがundefinedだったりしていませんか?

※notoNoはnoteNoのような気がしますが・・・

投稿2019/07/22 02:35

編集2019/07/22 02:39
yambejp

総合スコア114784

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

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

toloveru83

2019/07/22 02:59

ご回答ありがとうございます。 上記を追加して実行したところ nullと帰ってきました。 他の方の解答も参考に原因探ってみます!
yambejp

2019/07/22 03:10

存在しないidを指定しうるのであれば、分岐を入れる必要があります。 指定するものが必ず存在するはずであれば 指定の方法が間違えているのでしょう
guest

0

ベストアンサー

console.log()で出力してみると分かりますが、

js

1 function stopKey(notoNo){ 2 3 gain.value = 0; 4 console.log(notoNo); 5 console.log(document.getElementById("note"+notoNo)); //ここがnullになっている 6 document.getElementById("note"+notoNo).classList.remove("strike"); 7 }

よくよく見ると、init()の下記が原因のように見えます。

js

1 key.id = "note" + notoNo; 2 key.id = "key_" + i; //idが上書きされてる

投稿2019/07/22 02:33

m.ts10806

総合スコア80850

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

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

toloveru83

2019/07/22 03:24

ご回答ありがとうございます。 該当箇所のidを一つに統一すると改善されました。 idの重複が原因だったみたいです。 因みにidを複数に分けて使う(分岐させる)ということはできるのでしょうか?
m.ts10806

2019/07/22 03:34

ヒントになったようで何よりです。 >因みにidを複数に分けて使う(分岐させる)ということはできるのでしょうか? 同じ要素にID属性を複数当てることはできません。 具体的にどのような形(HTML)にしたいのでしょうか?
toloveru83

2019/07/22 07:51

"note + notoNo","key_ + i"共に後の構文にて使用(156行目 function checkNote()~など)するidのため、違う属性等ででも書き換えて使用できないかと思いまして。一つのidに統一して対応していくべきなのでしょうか?
m.ts10806

2019/07/22 07:56 編集

どうしてもというのでしたらdata*属性が有用かとは思いますが、 idで全部完結できるなら後のコードも同じIDを利用するように統一されたほうが良いとは思います。
toloveru83

2019/07/22 08:13

わかりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問