6.11 指定した時間毎に繰り返す

(1/1)
レンチキュラー印刷のイラスト
たとえばアニメーションでフレームを切り替えて画面が動いているように見せるとき、一定間隔で繰り返し処理を行う必要がある。こういうときに利用するのが setIntervalメソッドである。指定したミリ秒ごとに、指定した関数を実行することができる。
今回は、setIntervalメソッドを使ってデジタル時計を表示するプログラムと、雪を降らせるアニメーション・プログラムを作ってみることにする。

目次

サンプル・プログラム

圧縮ファイルの内容
digitalclock.htmlサンプル・プログラム(デジタル時計)
snowfall.htmlサンプル・プログラム(雪を降らせる)
digitalclock.html 更新履歴
バージョン 更新日 内容
1.0.0 2023/06/18 初版
snowfall.html 更新履歴
バージョン 更新日 内容
1.0.0 2023/06/18 初版

デジタル時計

初期値として以下の値を設定する。
スタイルシートなどへの設定は、windows.onload イベントを使って、このページがロードされるときに設定する。

  26: //初期値
  27: const TITLE = 'デジタル時計';       //プログラム・タイトル
  28: const REFERENCE = 'https://www.pahoo.org/e-soul/webtech/js00/js00-06-11.html';
  29:                                     //参照サイト
  30: const WIDTH  = 600;                 //時計の幅(ピクセル)
  31: const HEIGHT = 400;                 //時計の高さ(ピクセル)
  32: const CLOCK_NAME = 'pclock';        //時計のオブジェクト名【変更不可】
  33: const TIME_NAME  = 'pclock-time';   //時刻部分のオブジェクト名【変更不可】
  34: const DATE_NAME  = 'pclock-date';   //日付部分のオブジェクト名【変更不可】
  35: 
  36: // メイン・プログラム ======================================================
  37: window.onload = function() {
  38:     //タイトル等をセット
  39:     document.title = TITLE;
  40:     document.getElementById('title').innerHTML = TITLE + '&nbsp;<span style="font-size:small;">' + getLastModified() + '版</span>';
  41:     document.getElementById('reference').innerHTML =`
  42: ※参考サイト&nbsp;<a href="${REFERENCE}">${REFERENCE}</a>
  43: `;
  44:     document.getElementById('phelp').style.width = WIDTH + 'px';
  45: 
  46:     //時計のスタイルシートを設定する.
  47:     let pclock = document.getElementById(CLOCK_NAME);
  48:     pclock.style.width  = WIDTH  + 'px';
  49:     pclock.style.height = HEIGHT + 'px';
  50:     let pclock_date = document.getElementById(DATE_NAME);
  51:     pclock_date.style.fontSize = Math.round(WIDTH / 20+ 'px'
  52:     pclock_date.style.paddingTop = Math.round(HEIGHT / 8+ 'px'
  53:     let pclock_time = document.getElementById(TIME_NAME);
  54:     pclock_time.style.fontSize = Math.round(WIDTH / 6+ 'px'
  55:     pclock_time.style.paddingTop = Math.round(HEIGHT / 8+ 'px'
  56: //--ここまで初期設定

時計動作を開始する

  58:     //時計動作を開始する関数
  59:     function startClock() {
  60:         setInterval(function () {
  61:             var dt      = new Date();           //現在日時
  62:             let year    = dt.getFullYear();     //年
  63:             let month   = dt.getMonth() + 1;
  64:             let date    = dt.getDate();
  65:             let weeknum = dt.getDay();
  66:             const weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  67:             let week    = weekday[weeknum];
  68:             let hour    = dt.getHours();
  69:             let min     = dt.getMinutes();
  70:             let sec     = dt.getSeconds();
  71: 
  72:             //数字を2桁に揃える
  73:             month = zeroSuppress(month);
  74:             date  = zeroSuppress(date);
  75:             hour  = zeroSuppress(hour);
  76:             min   = zeroSuppress(min);
  77:             sec   = zeroSuppress(sec);
  78: 
  79:             //日付・時刻の文字列を作成
  80:             let today = `${year}.${month}.${date${week}`;
  81:             let time = `${hour}:${min}:${sec}`;
  82: 
  83:             //文字列を出力
  84:             document.getElementById(DATE_NAME).innerText = today;
  85:             document.getElementById(TIME_NAME).innerText = time;
  86: 
  87:         }, 1000);       //1000ミリ秒=1秒ごとに処理する
  88:     }

時計動作を開始するメソッドが startClock で、冒頭で紹介した setIntervalメソッドを使って、取得した現在日時を画面に1000ミリ秒(=1秒)ごとに繰り返し表示する。
すべの文字を再描画しているのだが、前回と変わらない文字はちらつかずに再描画される。

数字の桁数を揃える

 105: /**
 106:  * ゼロ・サプレスで数字をdigit桁に揃える.
 107:  * 与えた数字の頭に0を足して桁数を揃える.
 108:  * @param   String  num
 109:  * @param   Integer digit 数字の桁数
 110:  * @return  String 2桁の数字
 111: */
 112: function zeroSuppress(num, digit=2) {
 113:     let str = String(num);
 114:     str = '0'.repeat(digit+ str;
 115: 
 116:     return str.slice(-digit);
 117: }

与えた数字の頭に0を足して桁数を揃えるユーザー関数 zeroSuppress を用意した。桁数を指定するdigitは、デフォルト引数として2を与えている。
まず、与えた数値 num を文字列 str に変換する。
次に、repeatメソッドを使って、str の左側に '0' をdigit個結合する。
最後に、slice メソッドを使って、str の右側からdigit個の文字を取り出す。こうすることで桁合わせができる。

雪を降らせる

次に雪を降らせるプログラムであるが、初期値として以下の値を設定する。
アニメーションは、「6.9 グラフィックキャンバスとヒアドキュメント」で紹介した canvas要素を使う。
すべての準備や関数定義は、前述のデジタル時計と同じで、window.onload イベントの中で行う。

  26: //初期値
  27: const TITLE = '雪を降らせる';       //プログラム・タイトル
  28: const REFERENCE = 'https://www.pahoo.org/e-soul/webtech/js00/js00-06-11.html';
  29:                                     //参照サイト
  30: const INTERVAL = 50;                //再描画間隔(ミリ秒)
  31: const CANVAS_NAME = 'pcanvas';      //canvasオブジェクト名【変更不可】
  32: const WIDTH  = 600;                 //表示幅(ピクセル)
  33: const HEIGHT = 400;                 //表示高(ピクセル)
  34: const BGIMAGE = 'https://www.pahoo.org/athome/album/2014/img20150101-001454e.jpg';      //背景画像
  35: 
  36: // メイン・プログラム ======================================================
  37: window.onload = function() {
  38:     //タイトル等をセット
  39:     document.title = TITLE;
  40:     document.getElementById('title').innerHTML = TITLE + '&nbsp;<span style="font-size:small;">' + getLastModified() + '版</span>';
  41:     document.getElementById('reference').innerHTML =`
  42: ※参考サイト&nbsp;<a href="${REFERENCE}">${REFERENCE}</a>
  43: `;
  44:     document.getElementById('phelp').style.width = WIDTH + 'px';
  45: 
  46:     //canvas要素を取得する.
  47:     var canvas = document.getElementById(CANVAS_NAME);
  48:     //canvas要素にstyle設定する.
  49:     canvas.style.width  = WIDTH + 'px';
  50:     canvas.style.height = HEIGHT + 'px';
  51:     canvas.style.backgroundImage = "url('https://www.pahoo.org/athome/album/2014/img20150101-001454e.jpg')";
  52:     canvas.style.backgroundSize = 'cover';
  53: 
  54:     //Canvasの描画コンテキストを取得する.
  55:     var ctx = canvas.getContext('2d');
  56: 
  57:     //雪粒の数
  58:     var drops = [];
  59: //--ここまで初期設定

雪粒はオブジェクトで

  61:     //雪粒の設定
  62:     function snowDrop() {
  63:         //雪粒の初期位置をランダムに設定する.
  64:         this.x = Math.random() * canvas.width;
  65:         this.y = 0 - Math.random() * canvas.height;
  66: 
  67:         //雪粒の落下スピードを乱数で設定する.
  68:         this.speed = Math.random() * 10 + 5;
  69:         //雪粒の半径を乱数を使って設定する.
  70:         this.radius = Math.random() * 0.3 + 0.3;
  71: 
  72:         //雪粒を描画する.
  73:         this.draw = function () {
  74:             ctx.beginPath();
  75:             ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
  76:             ctx.fillStyle = 'Azure';
  77:             ctx.fill();
  78:             ctx.closePath();
  79:         }
  80:     }

  82:     //canvasに雪粒を追加する.
  83:     function addSnowDrop() {
  84:         drops.push(new snowDrop());
  85:     }

降らせる雪の粒1つ1つを snowDropメソッドで表す。
1つの snowDropオブジェクトが、1つの雪の粒を表していると考えてほしい。
canvas要素に雪粒を1つ追加するには、snowDropオブジェクトを1つ生成する。

snowDropオブジェクトには、雪粒の位置(x, y)や大きさ(radius)、落下スピード(speed)を、各々プロパティとして持たせてある。つまり、雪粒の位置や大きさ、落下スピードは、雪粒の1つ1つに対して独立に設定することができる。
これにより、アニメーションでは、早く落ちる雪粒や、ゆっくりと落ちる雪粒が混在し、あたかも雪が降っているように見せかけることができる。

雪粒はオブジェクトで

  87:     //雪粒の位置を更新する関数
  88:     function updateSnowDrops() {
  89:         for (var i = 0i < drops.lengthi++) {
  90:             //雪粒が落下するように見せかける.
  91:             drops[i].y +drops[i].speed;
  92:             //雪粒がcanvasの下端に達したら画面上から消す.
  93:             if (drops[i].y > canvas.height) {
  94:                 drops.splice(i, 1);
  95:                 i--;
  96:             }
  97:         }
  98:     }

 100:     //雪粒を描画する関数
 101:     function drawSnowDrops() {
 102:         for (var i = 0i < drops.lengthi++) {
 103:             drops[i].draw();
 104:         }
 105:     }

雪粒 snowDropオブジェクトの位置を更新する――つまり、雪粒が落ちていくようにするメソッドが updateSnowDropsである。snowDropオブジェクトのプロパティ speed を参照し、Y軸方向の位置を変化させていく。雪粒が canvas要素の下端に達したら画面上から消す(配列 drops から取り除く)。

アニメーションを開始する

 107:     //アニメーションを開始する関数
 108:     function startAnimation() {
 109:         setInterval(function () {
 110:             //canvasをクリアする.
 111:             ctx.clearRect(0, 0, canvas.width, canvas.height);
 112:             //雪粒を追加する.
 113:             addSnowDrop();
 114:             //雪粒の位置を更新する.
 115:             updateSnowDrops();
 116:             //雪粒を描画する
 117:             drawSnowDrops();
 118:         }, INTERVAL);
 119:     }

アニメーションを開始するメソッドが startAnimation で、冒頭で紹介した setIntervalメソッドを使って、canvas要素のクリア、雪粒の追加、位置の更新、雪粒の描画を50ミリ秒ごとに繰り返し実行する。

参考サイト

(この項おわり)
header