大きく表示するタイマーが欲しかったからdivのborderで数字を描いてみた

# はじめに

divのborderで数字を描いてみた話です。

## やりたかったこと
小学校の教室でタイマーを大きく表示したい。

## 背景
月に数回程度、小学校にお邪魔して[K3Tunnelを使ったプログラミング授業をお届け](https://qiita.com/cocoakamen/items/4380d8151c7c44033907) しています。

普通の授業時間にお邪魔するので、時間厳守。
時間厳守しないと給食時間や休み時間が短くなってしまいます。
出張授業なので、45分×2コマの1本勝負。
続きはまた今度ね。は許されません。

私たちがやっているプログラミング授業は、シナリオが用意された体験モノです。そのため、ここまでは到達してほしい、ここの面白さを感じてほしいというポイントがあります。

なので、時には、作業途中の子どもたちの手を止めて「次」に移ってもらったり。
ゆっくりゆっくりやっている子のペースアップを促したりすることもあります。

が。こんな感じのこどもたちを目にしたら。
![kids_doro_asobi_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/ea8c3452-f2ec-021b-0fa5-4647d3cdb4c3.png)

それがなかなか難しい。

**言いにくいことはAIに言わせる。**

これ。エンジニアの常識です。

**時間が来たよと機械的に伝える。**

終了時間を指定して時計を見てもらうだけでは弱い。
タイマーをセットして突然音を鳴らすのは心臓に悪い。
子どもたち自身のペースメイクを促したい。

**タイマーを大きく誰もが見える場所に表示するのがベスト。**

というのが私の結論でした。


## 対応方針
物理的な時計やタイマーアプリなどには目もくれず、**つくる。いいから作る。**
![nichiyoudaiku_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/7d4c6da2-5ef3-bdef-4de3-2fc8c2d8f274.png)

## 作成方針
**実装に使うモノについて学習しない。**
なぜならJavaScript/html/cssで何か作りたい熱が高まったのがトリガーで、「今日は時間が取れる」休日がぽっと生まれたときに作ることにしたから。

1日でぱぱっとつくれることが重要。
慣れない言語に手を出すなど論外。
初めてのライブラリやフレームワークに挑戦するとかもなし。

だがしかし。つくる。

## つくったもの
できあがりはこちらで確認できます。
https://cocoakamen.github.io/cocoa-timer/

#構想する
学習せずに作るといっても、特大フォントで時間表示するだけでは、いくらなんでも芸がない。
少しくらいはチャレンジ要素を入れたい。

と。

しばし考えて、思いついた。

ひょっとして。

divのborderを太くしたら、デジタル時計っぽくなるのでは？

とりあえず、このHTMLで、上下と左右で色を変えたdiv（縦横100pxで太さ20px）を表示してみた。

```html
<html>
  <div style="border-color:black gray; height:100px; width:100px; border-style:solid; border-width:20px;"></div>
</html>
```

結果。
![timer-try.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/a6bcd92f-1cf6-455f-28d9-a7810ba21a16.jpeg)

デジタル数字ができそうな気がする見た目をしている。

# 作る
## divを並べる

こんな感じにdivを並べることに。太枠のボックスが数字を描こうとしているdiv。
![timer-div.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/e49862e2-55a1-1321-7baa-11cd9e90d9bf.jpeg)
各数字、二つのdivを使うイメージ。
箱の中に書いてあるのはid名。
id名が書いていないのは、スペース調整用だったりなんだり。
classがいっぱいあるのは、スタイル設定するための色々。
もしかしたら使っていないclassもあるかもしれない。。

数字を表示しているところのHTMLはこちら。
上下それぞれ横に並べるのが少しややこしい。

```html:index.html
<div class="timer-container">
  <div class="number-row">
      <div class="digital-number number-left number-up" id="number-minute-left-up"></div>
      <div class="digital-blank-separater"></div>
      <div class="digital-number number-right number-up" id="number-minute-right-up"></div>
      <div class="digital-separater" id="separater-up"></div>
      <div class="digital-number number-left number-up" id="number-second-left-up"></div>
      <div class="digital-blank-separater"></div>
      <div class="digital-number number-right number-up" id="number-second-right-up"></div>    
  </div>
  <div class="number-row">
      <div class="digital-number number-left number-down" id="number-minute-left-down"></div>
      <div class="digital-blank-separater"></div>
      <div class="digital-number number-right number-down" id="number-minute-right-down"></div>
      <div class="digital-separater" id="separater-down"></div>  
      <div class="digital-number number-left number-down" id="number-second-left-down"></div>
      <div class="digital-blank-separater"></div>
      <div class="digital-number number-right number-down" id="number-second-right-down"></div>    
  </div>  
</div>
```

## borderのスタイルを決めていく

### 文字の太さ

cssの[:root 疑似クラス](https://developer.mozilla.org/ja/docs/Web/CSS/:root)に[カスタムプロパティ](https://developer.mozilla.org/ja/docs/Web/CSS/Using_CSS_custom_properties)で定義。

```css:timer.css

:root {
 --number-line-width: 30px;
}
```

digital-numberクラスにベースの設定をカキカキ。（数字を描くdiv要素は全部digital-number)

```css:timer.css
main .digital-number{
  border: solid;
  width:200px; 
  height:170px;
  border-width: var(--number-line-width); /* :root要素で設定しているカスタムプロパティ参照 */
  box-sizing: border-box; /* パディングとボーダーを幅と高さに含める */
}
/* 全体的にmain要素で囲っているのでmainがついてます */
```

上と下が重なり合うところは、それぞれ幅を2分の1にします。
こういうとき、カスタムプロパティを定義しておくと便利です。

```css:timer.css

main .number-up {
  border-bottom-width: calc( var(--number-line-width)/2);
}

main .number-down {
  border-top-width: calc( var(--number-line-width)/2);
}
```

### 文字の色

文字の色は、JavaScriptの中で指定。
コンストラクタ定義でベタ打ち定義。

```javascript:timer.js

function CocoaTimer() {
  this.numberColor = 'black'; // 文字の色
  this.GRAY_OUT_COLOR = '#EFEFEF'; // 線がない部分の色
  this.remainingTime = 0;
  this.timer = {};
};
```

### 数字をかく

表示する数字ごとに色を指定します。
こんなイメージ。
![number_color.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/eab7cbc0-25f8-9028-2e9b-ff9caf7b7911.jpeg)


あとは地道に定義していきました。引数は数字を描くdivの上と下の要素。

```javascript:timer.js

CocoaTimer.prototype.drawNumber = function(upElement, downElement, num) {
  // 中略
  // 数字
  switch(num) {
    case 0:
      upElement.style.borderColor = this.numberColor;
      upElement.style.borderBottomColor = this.GRAY_OUT_COLOR;
      downElement.style.borderColor = this.numberColor;
      downElement.style.borderTopColor = this.GRAY_OUT_COLOR;
      break;
    case 1:
      upElement.style.borderColor = this.GRAY_OUT_COLOR;
      upElement.style.borderRightColor = this.numberColor;
      downElement.style.borderColor = this.GRAY_OUT_COLOR;
      downElement.style.borderRightColor = this.numberColor;
      break;
    // 中略　以下9まで地道に定義
      break;
    default:
      break;
  }
};
```

## 時間は普通に計算

時間はミリ秒で計算。
残り時間のミリ秒から、分、秒それぞれ1の位と10の位の数字を求める計算をsetInterval使って実行して再描画。詳細は省略。
時間になったら点滅。今のところ音はなりません。

## ソースはこちらにも
https://github.com/cocoakamen/cocoa-timer

# 子どもたちの反応

授業で実際に使った時の反応はおおむね「やばい爆弾だ。爆弾。」
![jigenbakudan_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308852/8e979744-25a5-a417-a1f7-bd78aa9ececf.png)
なんですが、残念ながら、爆弾イフェクトは実装されておりません。

将来ゲームクリエイターになりたいんだ♪という子に、あのタイマー、私がつくったんだよと自慢したところ、尊敬のまなざしを得られた気がします。

もちろん、狙い通り、子どもたち自身が残り時間を意識している様子も見受けられ、ほくほくです。

# まとめ
タイマーを導入したら、子どもたちのフォローをするときに、時間を気にする脳ミソ使用量が減った気がします。ワークショップの進行がとてもラクになるのでお勧めです。

ちなみに、自分の子の小学校授業参観にいったら、物理タイマーを実物投影機で大きいディスプレイに映してました。