13章:まとめの演習2 タイピングゲームをつくろう
【13-1】タイピングゲームの仕様
- 配列に問題文を格納する
- ページロード時の処理
- データ送信時の処理
- もう1回ボタンクリック時の処理
- ブラウザを更新する
- Enter(return)キーを押したときと離したときの処理
- 送信ボタンの色を変化させる
- 「typing-game_fin」フォルダ内の「typing.html」は完成データですので、こちらのファイルをブラウザ表示して、まずは自分で遊んでみて下さい。
<body> <!-- 問題数とクリアした数 --> <div class="clear"> <span class="number-of-questions-cleared"></span>/<span class="number-of-questions" ></span> </div> <!-- 得点 --> <div class="score-box"><span class="score"></span>点</div> <div class="container"> <h1>タイピングゲーム</h1> <h2>俳句で練習しよう</h2> <form class="typing-form"> <!-- 問題文 --> <input type="text" class="elem-text elem1" /> <!-- 解答欄 --> <input type="text" class="elem-text elem2" /> <!-- 送信ボタン --> <input type="submit" value="解答を送信する" class="submit-btn" /> </form> <!-- もう一回ボタン --> <button class="onemore-btn">もう1回!</button> </div> </body>
【13-2】下準備をしよう
🟧 要素オブジェクトの作成
- form要素やinput要素、button要素、span要素など、オブジェクトとして操作したいDOMの要素は全てquerySelectorメソッドでclass名を取得し、定数に代入します。
- この作業を最初にまとめてやっておき、オブジェクト一覧を作成しておくと、見晴らしの良いコードを書くことができます。
- また、今回はJavaScriptを外部ファイルにして作成しますので、 </body> の直前 に scriptタグを記述して、 typing.html と typing.js を関連付けしておきましょう。 (サンプルコード13-2参照)
✔️ オブジェクトとして必要なDOM要素
・・・中略・・・ <script src="js/typing.js"></script> </body> </html>
//オブジェクト一覧 const formObj = document.querySelector(".typing-form"); const elemQuestion = document.querySelector(".elem1"); const elemAnswer = document.querySelector(".elem2"); const submitBtn = document.querySelector(".submit-btn"); const onemoreBtn = document.querySelector(".onemore-btn"); const questionsCleared = document.querySelector(".number-of-questions-cleared"); const numberOfQuestions = document.querySelector(".number-of-questions"); const score = document.querySelector(".score");
【13-3】初期画面を作成しよう
初期画面として設定する項目は、以下のとおりです。
✔️ 初期画面の設定項目
🟧 1. もう1回ボタンを非表示にする
- 「もう1回ボタン」はonemoreBtnというオブジェクト名で定義しました。(サンプルコード13-3参照)
- この要素オブジェクトの下位オブジェクトであるstyleオブジェクトにアクセスしてCSSを操作します。(「6章 JavaScriptでCSSを操作しよう」参照)
- CSSのdisplayプロパティの値をnoneと設定すれば非表示になります。
- オブジェクト一覧よりも下に、以下のコードを記述します。
//もう1回ボタンを非表示にする onemoreBtn.style.display = "none";
🟧 2. 問題文の数(配列データの数)とクリアした問題数(初期値0)を表示する
配列に問題文を格納する
- constで配列名haikuWordsを宣言し、[ ]内に一文づつ「,(カンマ)」で区切りながら文字列を代入します。
- 今回は全部で9問にしましたが、問題文の追加・削除は自由に行なって下さい。
//配列に問題文を格納する const haikuWords = ["古池や", "蛙飛び込む", "水の音", "柿食えば", "鐘が鳴るなり", "法隆寺", "閑かさや", "岩にしみ入る", "蝉の声"]
問題文の数(配列データの数)を表示する
- 配列に格納されているデータの数は、lengthプロパティで取得できます。
- constで宣言した定数questionsNumに配列データの数を代入してから、サンプルコード13-3で作成したspan要素オブジェクトのnumberOfQuestionsにtextContentプロパティで出力します。
//問題文の数を表示 const questionsNum = haikuWords.length; numberOfQuestions.textContent = questionsNum;
クリアした問題数(初期値0)を表示する
- letで宣言した変数questionsClearedNumに0を代入します。
- letで宣言した変数を使う理由は、1問正解する度に1を加算し、値を再代入する必要があるためです。
- constで宣言した定数には、値を再代入することができません。(「7章 変数と定数を学ぼう」を参照)
- サンプルコード13-3で作成したspan要素オブジェクトのquestionsClearedにtextContentプロパティで変数の中身を出力します。
//クリアした問題数の初期化と表示 let questionsClearedNum = 0; questionsCleared.textContent = questionsClearedNum;
🟧 3. 得点(初期値0)を表示する
- constで宣言した定数には、値を再代入することができません。(「7章 変数と定数を学ぼう」を参照)
//得点の初期化と表示 let scoreNum = 0; score.textContent = scoreNum;
🟧 4. 問題欄に1問目を表示する
- 1問目のデータにはhaikuWords[0]でアクセスできます。
- 2問目のデータにはhaikuWords[1]でアクセスできます。(「11章 配列を学ぼう」参照)
- そのため、インデックス番号の初期値0をletで宣言した変数indexNumに格納しておくことにより、再代入が可能な状態にしておきます。
- その際、elemQuestion.value = haikuWords[indexNum];と記述することにより、初期状態で0にしてある配列のインデックス番号を、1問正解する度に1、2、3、4、5、6・・・・と増やしていくことができます。
- elemQuestion.value = haikuWords[0];と書いてしまうと、1問目が表示されはしますが、上記の処理ができません。
//配列のインデックス番号の初期化 let indexNum = 0; //1問目を表示 elemQuestion.value = haikuWords[indexNum];
🟧 5. 解答欄にカーソルを立てる
//解答欄にカーソルを立てる elemAnswer.focus();
ここまでに記述したコード全体です。
//オブジェクト一覧 const formObj = document.querySelector(".typing-form"); const elemQuestion = document.querySelector(".elem1"); const elemAnswer = document.querySelector(".elem2"); const onemoreBtn = document.querySelector(".onemore-btn"); const submitBtn = document.querySelector(".submit-btn"); const questionsCleared = document.querySelector(".number-of-questions-cleared"); const numberOfQuestions = document.querySelector(".number-of-questions"); const score = document.querySelector(".score"); //配列に問題文を格納する const haikuWords = ["古池や", "蛙飛び込む", "水の音", "柿食えば", "鐘が鳴るなり", "法隆寺", "閑かさや", "岩にしみ入る", "蝉の声"] //もう一回ボタンを非表示にする onemoreBtn.style.display = "none"; //問題文の数を表示 const questionsNum = haikuWords.length; numberOfQuestions.textContent = questionsNum; //クリアした問題数の初期化と表示 let questionsClearedNum = 0; questionsCleared.textContent = questionsClearedNum; //得点の初期化と表示 let scoreNum = 0; score.textContent = scoreNum; //配列のインデックス番号の初期化 let indexNum = 0; //1問目を表示 elemQuestion.value = haikuWords[indexNum]; //解答欄にカーソルを立てる elemAnswer.focus();
【13-4】データ送信時の処理を作成しよう
初期画面の表示が完成したら、データ送信時のイベント処理を作成します。
作成する項目が多いですが、順番に片づけていきます。
データ送信時のイベント処理として作成する項目は、以下のとおりです。
✔️ データ送信時のイベント処理項目
submitイベントを設定する
- submitイベントは、フォームのデータ送信時(送信ボタンをクリックしたとき)に発生するイベントです。
- submitイベントは、form要素に設定します。
- 今回作成するタイピングゲームにおいて、ユーザーが入力した解答が問題文と一致するかどうかを判別するタイミングを、submitイベント発生時にした理由は次のとおりです。
- 送信ボタン<input type=”submit”>は、ボタンを直接クリックする以外にも、Enterキー(returnキー)の押下でもsubmitイベントが感知されるため、ゲームの操作がしやすい。
- 通常のボタン<input type=”button”>、<button></button>は、Enterキー(returnキー)の押下では反応しない。
formObj.addEventListener("submit", function (e) { //ここにsubmitイベント発生時の処理を作成する }
- イベントオブジェクトのpreventDefaultメソッドを使用した処理を作成するため、引数にeを記述しておきます。
🟧 1. 解答欄に入力されたテキストを取得する
- 今回は入力内容の取得のために使用しています。
//解答欄に入力されたテキストを取得 const inputAnswer = elemAnswer.value;
🟧 2. 現在表示されている問題文と解答が同一かどうかを判別する
✔️ if文で行う処理内容
条件式
- inputAnswerが解答欄に入力されたテキスト、 haikuWords[indexNum]で配列データにアクセスします。
- indexNumには、はじめ0が代入されていますので、最初の送信イベント発生時には、1問目のテキストが、==演算子により、解答文と等しいかどうかが判別されます。
if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueの場合の処理 }
a. 同一だった場合、次の問題文を表示し、解答欄を空欄にして、カーソルを立てる
- 次の問題文を表示する
- ページロード時の変数indexNumには0が格納されていますので、elemQuestion.value = haikuWords[0];が実行され、1問目が表示されます。
- 2問目を表示するためには、elemQuestion.value = haikuWords[1];となればよいので、indexNumに1を加算します。
- 正解する度に、indexNumに1ずつ加算していけば、配列データの順番で問題文が切り替わっていきます。
- 「indexNumに1ずつ加算」をインクリメント演算子++を使い、indexNum++;と表します。(「7章 変数と定数を学ぼう」参照)
- 変数の中身が変化しただけでは、テキストフォームの表示は変わりません。
- 次の行で、elemQuestion.value = haikuWords[indexNum];と記述し、再度問題欄に配列データを表示させます。
- 解答欄を空欄にして、カーソルを立てる
- 「解答欄を空欄にする」は、テキストフォームのvalueプロパティを空の文字列にするということですので、elemAnswer.value = "";となります。
- 「テキストフォームにカーソルを立てる」はfocusメソッドを使い、elemAnswer.focus();となります。
if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にして、カーソルを立てる elemAnswer.value = ""; elemAnswer.focus(); }
b. 空欄または問題文と解答欄が不一致だった場合、問題文はそのままで、解答欄を空欄にして、カーソルを立てる
- 「問題文と解答が同一だった場合」以外は、空欄または不一致の場合となります。
- したがって、b.の条件は、サンプルコード13-12のif文以降にelse文を追加することにより表すことができます。
if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); } else { //条件式がfalseの場合(空欄・問題文と不一致) //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); }
c. a.とb.どちらの場合もイベントをキャンセルする(送信中止)
- 最後に、a.とb.どちらの場合もイベントをキャンセルすることにより、データの送信を中止します。
- データの送信を中止しないと、HTMLの仕様でページが更新され、初期表示に戻ってしまいます。
- if〜else文のブロック{}の外側で最後にイベントオブジェクトのpreventDefaultメソッドを参照すれば、submitイベント発生時に必ずデータの送信が中止されます。
- 最後の問題文(配列データ)が表示された後も変数indexNumには1が加算されます。
- その結果、配列内には存在しないhaikuWords[9]を参照し、問題欄に表示しようとするため、9問目の次はエラーメッセージであるundefined(未定義値)が表示されます。
- この不具合は後ほど解決していきます。
formObj.addEventListener("submit", function (e) { ・・・中略・・・ if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); } else { //条件式がfalseの場合(空欄・問題文と不一致) //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); } //イベントキャンセル e.preventDefault(); });
🟧 3. 1問正解する度に、得点に100点加算される
- サンプルコード13-8の変数scoreNumが得点を格納するための変数です。
- 変数scoreNumには、ページロード時の得点の初期値として0が代入されています。
- この変数scoreNumに100加算する処理は、scoreNum += 100;です。
- この処理を、if文の条件式がtrueだった場合に実行します。
- 次に、score.textContent = scoreNum;を記述し、加算処理後の変数の中身をspan要素オブジェクトであるscore内にtextContentプロパティで出力します。
//得点の初期化と表示 let scoreNum = 0; score.textContent = scoreNum;
if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); //1問正解する度に100点加算される scoreNum += 100; score.textContent = scoreNum; } else { //条件式がfalseの場合(空欄・問題文と不一致) //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); }
🟧 4. 1問正解する度に、問題をクリアした数がカウントされる
- サンプルコード13-7の変数questionsClearedNumがクリアした問題数を格納するための変数です。
- 変数questionsClearedNumには、ページロード時のクリアした問題数の初期値として0が代入されています。
- この変数questionsClearedNumに1加算する処理は、インクリメント演算子++を使い、questionsClearedNum++;で表すことができます。
- この処理を、if文の条件式がtrueだった場合に実行します。
- 次に、questionsCleared.textContent = questionsClearedNum;を記述し、加算処理後の変数の中身をspan要素オブジェクトであるquestionsCleared内にtextContentプロパティで出力します。
//クリアした問題数の初期化と表示 let questionsClearedNum = 0; questionsCleared.textContent = questionsClearedNum;
if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); //1問正解する度に100点加算される scoreNum += 100; score.textContent = scoreNum; //1問正解する度に問題をクリアした数がカウントされる questionsClearedNum++; questionsCleared.textContent = questionsClearedNum; } else { //条件式がfalseの場合(空欄・問題文と不一致) //解答欄を空欄にする elemAnswer.value = ""; //解答欄にカーソルを立てる elemAnswer.focus(); }
🟧 5. 全問クリアしたとき
続いて、全問クリアしたときの処理を作成していきます。
以下のa〜eまでの処理を順番に作成します。
✔️ 全問クリアしたときの処理内容
まずは、全問クリアしたかどうかを判別するための条件分岐を記述します。
if文の条件式と、そのif文をどこに記述するかが重要です。
if文は入れ子構造にできる
- 変数questionsClearedNumにはクリアした問題の数が入っており、定数questionsNumには問題数が入っていますので、両者が等しいかどうかを判別する演算子==を使い以下の条件式を記述します。
if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 }
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 } }
a. アラートでメッセージを出す(「全問正解おめでとう! ボーナスポイント100点追加!」)
- 入れ子にしたif文の{ }内に、全クリアしたときの処理内容を書いていきます。
- alertメソッドでメッセージを出力します。
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); } }
b. ボーナスポイントを100点追加する
- 続いて、得点にボーナスポイントを100点追加する処理を加えます。
- ここまでに獲得した得点は、変数scoreNumに入っていますから、
- scoreNum += 100;で100を加算した後、span要素オブジェクトである定数scoreのtextContentプロパティを使って、最終的な得点を出力します。
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); //ボーナスポイントを100点追加する scoreNum += 100; score.textContent = scoreNum; } }
c. 1問目を再表示する
- ゲームが終了したしるしとして、問題欄には1問目を再表示します。
- 配列のインデックス番号が格納されている変数indexNumに0を再代入してから、input要素オブジェクトである定数elemQuestionのvalueプロパティに配列データhaikuWords[indexNum]を=でセットすれば、1問目が再表示されます。
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); //ボーナスポイントを100点追加する scoreNum += 100; score.textContent = scoreNum; //1問目を再表示 indexNum = 0; elemQuestion.value = haikuWords[indexNum]; } }
d. 送信ボタンを無効にする
- このままでは、タイピングゲームをさらに続けていくことができ、正解するたびに得点とクリアした問題数が加算されてしまいます。
- そこで、送信ボタンを無効にすることにより、イベント処理が実行されないようにします。
- フォームのボタン要素オブジェクトは、無効状態を指定するためのdisabledというプロパティを持っています。このプロパティの値は初期設定がfalseとなり、有効の状態になっています。
- これを無効にするには、trueをセットします。
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); //ボーナスポイントを100点追加する scoreNum += 100; score.textContent = scoreNum; //1問目を再表示 indexNum = 0; elemQuestion.value = haikuWords[indexNum]; //送信ボタンを無効にする submitBtn.disabled = true; } }
e. もう1回ボタンを表示する
- タイピングゲームを初期画面に戻すための「もう一回ボタン」を表示させます。
- サンプルコード13-4で非表示にした「もう1回ボタン」を表示するためには、CSSのdisplayプロパティの値をblockに設定すればよいので、onemoreBtnオブジェクトの下位オブジェクトのstyleオブジェクトにアクセスし、onemoreBtn.style.display = "block";と記述します。
if (inputAnswer == haikuWords[indexNum]) { ・・・中略・・・ if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); //ボーナスポイントを100点追加する scoreNum += 100; score.textContent = scoreNum; //1問目を再表示 indexNum = 0; elemQuestion.value = haikuWords[indexNum]; //送信ボタンを無効にする submitBtn.disabled = true; //もう一回ボタンを表示する onemoreBtn.style.display = "block"; } }
【13-5】もう1回ボタンクリック時の処理を作成しよう
- もう1回ボタンクリック時に、初期画面の状態に戻します。
- 簡単な方法としては、ページをリロード(更新)すれば、初期画面に戻りますので、今回はその方法を採用します。
- ブラウザオブジェクトのlocationオブジェクトが持っているreloadメソッドを使うと、ページをリロードすることができます。
- もう1回ボタンにclickイベントを設定し、location.reload();と記述すれば完了です。
//もう一回ボタンクリック時にページを更新する onemoreBtn.addEventListener("click", function () { location.reload(); })
【13-6】Enter(return)キーを押したときと離したときの処理を作成しよう
- イベントオブジェクトのkeyプロパティを使うと、押したキーに割り当てられた文字列を返します。
- Enterキーの場合は”Enter”、
- 数字の1の場合は”1”、
- 右の方向キーの場合は”ArrowRight”をそれぞれ返します。
- if文の条件式をe.key == "Enter"と記述すれば、Enter(return)キーが押された場合にtrueが返ってきます。
- JavaScript Key Code
if文の条件分岐でEnter(return)キーが押されたかどうかを判別する
- keydown、keyupイベントは共にdocumentオブジェクトに設定します。
- documentはページ全体のDOMにアクセスできるため、キーボード関連のイベントがページ全体に対して確実に反応します。
// enter(return) キーを押したときに送信ボタンの色変化 document.addEventListener("keydown", function (e) { if (e.key == "Enter") { submitBtn.style.backgroundColor = "#4fe1e4"; } }) document.addEventListener("keyup", function (e) { if (e.key == "Enter") { submitBtn.style.backgroundColor = "#00bec1"; } })
【13-7】完成
完成したコード全体です。
<body> <!-- 問題数とクリアした数 --> <div class="clear"> <span class="number-of-questions-cleared"></span>/<span class="number-of-questions" ></span> </div> <!-- 得点 --> <div class="score-box"><span class="score"></span>点</div> <div class="container"> <h1>タイピングゲーム</h1> <h2>俳句で練習しよう</h2> <form class="typing-form"> <!-- 問題文 --> <input type="text" class="elem-text elem1" /> <!-- 解答欄 --> <input type="text" class="elem-text elem2" /> <!-- 送信ボタン --> <input type="submit" value="解答を送信する" class="submit-btn" /> </form> <!-- もう一回ボタン --> <button class="onemore-btn">もう1回!</button> </div> <script src="js/typing.js"></script> </body>
//オブジェクト一覧 const formObj = document.querySelector(".typing-form"); const elemQuestion = document.querySelector(".elem1"); const elemAnswer = document.querySelector(".elem2"); const onemoreBtn = document.querySelector(".onemore-btn"); const submitBtn = document.querySelector(".submit-btn"); const questionsCleared = document.querySelector(".number-of-questions-cleared"); const numberOfQuestions = document.querySelector(".number-of-questions"); const score = document.querySelector(".score"); //配列に問題文を格納する const haikuWords = [ "古池や", "蛙飛び込む", "水の音", "柿食えば", "鐘が鳴るなり", "法隆寺", "閑かさや", "岩にしみ入る", "蝉の声", ]; //もう一回ボタンを非表示にする onemoreBtn.style.display = "none"; //問題文の数を表示 const questionsNum = haikuWords.length; numberOfQuestions.textContent = questionsNum; //クリアした問題数の初期化と表示 let questionsClearedNum = 0; questionsCleared.textContent = questionsClearedNum; //得点の初期化と表示 let scoreNum = 0; score.textContent = scoreNum; //配列のインデックス番号の初期化 let indexNum = 0; //1問目を表示 elemQuestion.value = haikuWords[indexNum]; //解答欄にカーソルを立てる elemAnswer.focus(); //送信イベントの設定 formObj.addEventListener("submit", function (e) { //解答欄に入力されたテキストを取得 const inputAnswer = elemAnswer.value; //if文で現在表示されている問題文と同一かどうか判別する if (inputAnswer == haikuWords[indexNum]) { //条件式がtrueだった場合、次の問題文を表示する indexNum++; elemQuestion.value = haikuWords[indexNum]; //解答欄を空欄にして、カーソルを立てる elemAnswer.value = ""; elemAnswer.focus(); //1問正解する度に100点加算される scoreNum += 100; score.textContent = scoreNum; //1問正解する度に問題をクリアした数がカウントされる questionsClearedNum++; questionsCleared.textContent = questionsClearedNum; //全問クリアしたらアラートでメッセージを出す //ボーナスポイント100点追加する if (questionsClearedNum == questionsNum) { //全問クリアしたときの処理 //alertメソッドでメッセージを出力 alert("全問正解おめでとう! ボーナスポイント100点追加!"); scoreNum += 100; score.textContent = scoreNum; //1問目を再表示 indexNum = 0; elemQuestion.value = haikuWords[indexNum]; //送信ボタンを無効にする submitBtn.disabled = true; //もう一回ボタンを表示する onemoreBtn.style.display = "block"; } } else { //条件式がfalseの場合(空欄・問題文と不一致) elemAnswer.value = ""; elemAnswer.focus(); } //イベントキャンセル e.preventDefault(); }); //もう一回ボタンクリック時にページを更新する onemoreBtn.addEventListener("click", function () { location.reload(); }); // enter(return) キーを押したときに送信ボタンの色変化 document.addEventListener("keydown", function (e) { if (e.key == "Enter") { submitBtn.style.backgroundColor = "#4fe1e4"; } }); document.addEventListener("keyup", function (e) { if (e.key == "Enter") { submitBtn.style.backgroundColor = "#00bec1"; } });
これで「13章:まとめの演習2 タイピングゲームをつくろう」の解説を終わります。
最後にJavaScript課題「DOMの操作」に取り組みましょう。