📅 note公開日:2025-08-30 22:07
🔁 この記事はnoteで公開していた内容をQiitaへ移行・再掲したものです。(必要に応じて加筆修正しています)
最終章ステップ3です!
ステップ3 (advanced)
UIの演出を追加して完成度をUPさせましょう。
以下の要件を達成してください👇
- 勝敗結果に応じて文字色がネオン風に変化
- チートモードON時に背景が変化するアニメーションを追加
1:勝敗結果に応じて文字色がネオン風に変化
課題の始めに渡された文字色変更用CSS
.win { color: #57aaff; }
.lose { color: #ff5555; }
.draw { color: #00ff99; }
これと、前章で使用した
let plHand;
if (btn.textContent.includes("グー")) {
plHand = 0;
} else if (btn.textContent.includes("チョキ")) {
plHand = 1;
} else {
plHand = 2;
}
こちら。
この2つのコードをヒントにでなんとか書けるはず!
以下、作成したコード
// 勝敗に応じて色を替える
let textcolor;
if (result.textContent.includes("あいこ")) {
textcolor = "draw";
} else if (result.textContent.includes("勝ち")) {
textcolor = "win";
} else {
textcolor = "lose";
}
このままではまだなにも動かない。
ここからが面白い!
以下のコードを先述のコード真下に配置。
result.classList.add("win");
result の classList に文字列 "win" を追加。というコード。
指示通り実行されるとHTMLのresultはこうなる↓
<p id="result" class="win">あなたの勝ち!</p>
HTMLのclass要素はCSS読込み用プロパティ。
CSS側には以下のコードが配置されていた。
.win { color: #57aaff; }
.lose { color: #ff5555; }
.draw { color: #00ff99; }
copy
classを作成すると見込んでメンターが仕込んだコード。なるほど〜。
そもそもこういう書き方をする物だということを自分が知らないから感動してるだけかもしれないですが、、、
これはいいですね!いろんなパーツがパズルのように綺麗にはまっていく☺️
というわけで出来上がったコードがこちら
// 勝敗に応じて色を替える
let textcolor;
if (result.textContent.includes("あいこ")) {
textcolor = "draw";
} else if (result.textContent.includes("勝ち")) {
textcolor = "win";
} else {
textcolor = "lose";
}
result.classList.add("draw");
result.classList.add("win");
result.classList.add("lose");
最後の3行まとめれるので最終形態はこちら
// 勝敗に応じて色を替える
let textcolor;
if (result.textContent.includes("あいこ")) {
textcolor = "draw";
} else if (result.textContent.includes("勝ち")) {
textcolor = "win";
} else {
textcolor = "lose";
}
result.classList.add(textcolor); // textcolor変数を代入に変更
でも、これだと1回目の結果の色が出続けてしまう。。。
その対策として result.classList.remove("draw","win","lose"); をaddの上に追記する。
古いものを消して→新しいものを追記する循環🔁
let textcolor;
if (result.textContent.includes("あいこ")) {
textcolor = "draw";
} else if (result.textContent.includes("勝ち")) {
textcolor = "win";
} else {
textcolor = "lose";
}
result.classList.remove("draw", "win", "lose");
result.classList.add(textcolor);
この時、⚠️ addに合わせてカッコ内を("textcolor")にしないこと!
「class="textcolor"を外して」という指示になってしまう。
今回は let textcolor; で変数として textcolor を使用しており、class要素の textcolor が存在しているわけではないので、意味のないコードになる。
これで1回目の色が出続けることはなくなったけど、
なぜかランダムで色が変わる。。。なんでやねん💦
一部一致じゃだめなのか??探してる文字列が間違えているのか?
無理やり一部一致で通すのは諦め!!
結果を表す outcome を変数として定義し、
- あいこ=0
- 勝ち=1
- 負け=2
として、数字を拾って来させる方法に変更。
結果表示変数 outcome を使う版
// 結果表示変数 outcome 設定
let outcome; // あいこ0、勝ち1、負け2
// グー=0, チョキ=1, パー=2
// 勝敗判定
if (plHand === 0) {
if (cpuHand === 0) {
result.textContent = "あなた:グー 相手:グー →あいこ!";
outcome = 0;
} else if (cpuHand === 1) {
result.textContent = "あなた:グー 相手:チョキ →あなたの勝ち!";
outcome = 1;
} else {
result.textContent = "あなた:グー 相手:パー →あなたの負け!";
outcome = 2;
}
} else if (plHand === 1) {
if (cpuHand === 1) {
result.textContent = "あなた:チョキ 相手:チョキ →あいこ!";
outcome = 0;
} else if (cpuHand === 2) {
result.textContent = "あなた:チョキ 相手:パー →あなたの勝ち!";
outcome = 1;
} else {
result.textContent = "あなた:チョキ 相手:グー →あなたの負け!";
outcome = 2;
}
} else {
if (cpuHand === 2) {
result.textContent = "あなた:パー 相手:パー →あいこ!";
outcome = 0;
} else if (cpuHand === 0) {
result.textContent = "あなた:パー 相手:グー →あなたの勝ち!";
outcome = 1;
} else {
result.textContent = "あなた:パー 相手:チョキ →あなたの負け!";
outcome = 2;
}
}
// outcome → クラス名に変換
let textcolor;
if (outcome === 0) {
textcolor = "draw";
} else if (outcome === 1) {
textcolor = "win";
} else {
textcolor = "lose";
}
result.classList.remove("draw", "win", "lose");
result.classList.add(textcolor);
これでうまいこと動きました✨
解説
-
let outcome;は先頭に!
→//勝敗判定の中で使用しているから。 - ↓の部分は
//勝敗判定が終わってから!
if (outcome === 0) {
textcolor = "draw";
} else if (outcome === 1) {
textcolor = "win";
} else {
textcolor = "lose";
}
let outcome; に合わせて先頭に置いてしまうと、
outcome に何も代入されていない状態で正誤判定をすることになり、正常に動きませんでした。(実験済み)
2:チートモードON時に背景が変化するアニメーションを追加
ヒント1:ここにコード付け足すんだろうな〜。
cheat.addEventListener('change', (e) => {
cheatOn = e.target.checked;
if (e.target.checked) {
console.log('チートモードON')
} else {
console.log('チートモードOFF')
}
});
ヒント2:ほぼ答え書いてくれてる😭
/* チートモードがONになったときに適用されるアニメーション */
/* bodyに .cheat-active がつくと .overlay にこのアニメが発動 */
.cheat-active .overlay {
animation: cheatGlow 1s infinite alternate;
}
完成コードはこちら
cheat.addEventListener('change', (e) => {
cheatOn = e.target.checked;
if (e.target.checked) {
document.body.classList.add('cheat-active');
console.log('チートモードON')
} else {
document.body.classList.remove('cheat-active');
console.log('チートモードOFF')
}
});
解説
- チェックボックスのON/OFFに反応する様、イベントハンドラーに仕様を追加する。
- ヒントの「bodyに .cheat-active がつく」とは
<body class="cheat-active">となる状態。 -
.cheat-active .overlay {と記述があることから、bodyにクラスが付けばoverlay側にアニメーションが当たる。
チートモードON/OFF時の要素をチェックしてみた。
チェックする場所は <body> 要素。
チートモードがONになるとちゃんと body.cheat-active になっていることを確認。
そんなこんなで今回のクエスト終了致しました。
まだ個人的に進めたいことが2つ。
- 自分のコードの軌跡を残してみたくて消す予定のコードを全てコメントアウトで残している。
- まとめれそうなコードをあえて初期状態のまま置いてあるので、まとめられるところはどんどん関数化させていく。
この2点をやったら成果物としてpushしようかな。と思っています。
まとめ(Conclusion)
- UIの色変化は CSSクラス(win/lose/draw)をJSで付け替えることで実装できた。
-
classList.remove()→classList.add()の順にして、色が残り続ける問題も解消できた。 - 文言での判定が不安定だったので、outcome(勝敗)を数値で管理する方法に切り替えて安定した。
- チート背景は bodyに cheat-active を付け外しするだけでCSS側の演出が動くようになった。


