コンテンツにスキップ

ボタン・関数・変数で画像を動かす

指導者向けの公開補足

学習本文に加えて、指導の視点・背景・授業での確かめ方を示します。どなたでも読めます。

指導の焦点

固定値の代入と現在値に基づく更新を、複数回のクリックで比較させる。変数の値の変化と、画面へ値を反映する操作を混同しないようにする。

一歩踏み込んだ背景

イベントの登録時に関数を渡すことと、その場で関数を呼び出すことは異なる。変数を関数の外へ置く理由も、クリックをまたぐ状態の保持から説明する。

授業での確かめ方

クリック前後のsizeと画像幅を表にする。固定値の代入、変化量の変更、関数内での初期化を一か所ずつ試し、予想との違いを言葉で説明させる。

制度・規格等は本文末尾の参考資料も確認してください。

JSFiddleでコードを試す

JSFiddleは、ブラウザーでHTML・CSS・JavaScriptを入力して実行できるサービスです。短い動作確認から始められます。

  1. 新しい編集画面を開きます。JavaScriptは通常のJavaScriptを選び、外部ライブラリは追加しません。
  2. HTML欄にはページの本文、CSS欄には見た目、JavaScript欄には処理を書きます。HTML欄に<html>や<body>は不要です。JavaScript欄に<script>は付けません。
  3. DOMを使う例では、JavaScriptの実行タイミングを「On Load」「On DOM Ready」または「No wrap - bottom of body」にします。
  4. 「Run」を押してResult欄を確認します。書き換えたら再びRunを押します。

console.logの結果は通常、ページではなく開発者ツールのコンソールに出ます。このサイトの計算例をResult欄で読みたいときは、HTML欄に次を入れます。

<pre id="output"></pre>

JavaScript欄には次を入れ、console.log(2 + 3);の行を、試したいコード一つに置き換えます。独立した例を複数まとめて貼らないでください。

{
  const output = document.getElementById("output");
  const console = {
    log(...values) {
      output.textContent += values.join(" ") + "\n";
    }
  };
  console.log(2 + 3);
}

Runを押すと「5」と表示されます。外側の波括弧の中だけで表示用のconsoleを用意しているため、ブラウザー本来のコンソールは変更しません。

HTMLとJavaScriptの両方を載せた実習例は、この表示用コードで囲まず、それぞれの欄へ分けて貼り付けます。保存・共有時は公開範囲を確認し、個人情報やパスワードを入力しないでください。コードは手元にも残しましょう。

NAS・GitHub・CodePenなど、作業環境の選び方

この単元でできるようになること

Section titled “この単元でできるようになること”
  • HTMLの部品をidで見つけ、クリックと関数を結び付けられる。
  • 固定値を代入する処理と、現在の値を更新する処理を区別できる。
  • 変数の値と、画面に表示された状態の関係を説明できる。
  • DOM:HTML文書を、プログラムから部品ごとに操作できる形で表したもの。
  • イベント:クリックなど、操作や状態変化によって発生する出来事。
  • 関数:呼び出して実行できる処理のまとまり。
  • 変数:値を名前と結び付け、参照や更新に使う仕組み。
  • 代入:右辺の値を、左辺で指定した変数やプロパティへ設定すること。

準備ページの方法で、下の全体をresize.htmlとして保存して開こう。画像の丸はHTMLの中に埋め込んであるので、別の画像ファイルはいらない。

JSFiddleでは<body>内の画像・段落・ボタンをHTML欄へ、<script>内をJavaScript欄へ分ける。以後の実習も同じ方法で試せる。

resize.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>画像と変数</title>
</head>
<body>
<h1>画像の大きさを変える</h1>
<div style="max-width: 100%; overflow: auto">
<img id="picture" alt="緑の丸" width="160"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100'%3E%3Ccircle cx='80' cy='50' r='40' fill='seagreen'/%3E%3C/svg%3E">
</div>
<p id="size-label" aria-live="polite">幅:160px</p>
<button id="grow" type="button">40px大きくする</button>
<script>
const picture = document.getElementById("picture");
const label = document.getElementById("size-label");
const growButton = document.getElementById("grow");
let size = 160;
function grow() {
size = size + 40;
picture.width = size;
label.textContent = "幅:" + size + "px";
}
growButton.addEventListener("click", grow);
</script>
</body>
</html>

初めは160px、1回押すと200px、2回押すと240pxになる。再読み込みするとプログラムが初めから動くため、160pxへ戻る。ここでは上限を設けていないので、何回も押すと横にスクロールする必要がある。

クリックから画面が変わるまで

Section titled “クリックから画面が変わるまで”
  1. getElementById("grow")で、id="grow"のボタンを探す。
  2. addEventListener("click", grow)で、クリックされたらgrowを呼ぶように登録する。
  3. growの中でsizeを更新し、その値を画像の幅と説明文へ反映する。

growと書くのは、呼び出す関数を登録するためである。ここでgrow()と書くと、その場で関数を実行してしまう。idは一つのページで重複させず、文字の大小も一致させる。

size = size + 40;をsize = 240;へ置き換えてみよう。最初のクリックで240pxになるが、それ以降は変わらない。何回実行しても同じ値を代入しているためである。

size = size + 40;は等式ではない。右辺で現在の値に40を足し、その結果を左辺のsizeへ代入する。

let size = 160;を関数の中へ移すと、呼び出すたびに160からやり直してしまう。クリックをまたいで値を覚えるため、この例では関数の外で用意している。

変化量を20pxへ変更し、3回押した後の幅を予想して確かめよう。小さくするボタンを追加したい場合は、別のidのボタンと関数を用意し、減算と画面の更新を登録する。幅が小さくなりすぎる問題は、次の条件分岐で解決する。

  1. 初期値160から、元のコードで3回ボタンを押すと幅はいくつになるか。
  2. 更新行をsize = 240;へ変えると、2回目以降に見た目が変わらないのはなぜか。
  3. let size = 160;を関数の中へ移すと、連続して大きくならないのはなぜか。
問1の解答例を見る

160+40×3=280pxとなる。クリックごとに変数sizeの現在値へ40を加え、その値を画像の幅へ反映する。

問2の解答例を見る

毎回240という同じ値を代入しているため。現在の値への加算ではないので、既に240になった後は見た目が変わらない。

問3の解答例を見る

関数を呼び出すたびにsizeが160で初期化される。その後40を加えても毎回200となり、前のクリックで変わった値を引き継げない。

イベントと関数で操作を結び付け、変数で前の状態を覚える。更新した値を画面へ反映して動きを作る。次は条件分岐で大きさと表示を切り替えるへ進もう。