JavaScriptを全く使ったことのないヤツがElectronで時計を作るまで。[前編]

#きっかけ
RaspberryPiを搭載した多機能目覚まし時計を作ろうと模索しているのだが、作る際にディスプレイ部分をどう作るか？となった。
よく使うPythonでKivyやTkinterを使っても良かったのだが、せっかくなら「今まで敬遠していたJSに慣れる」という目的を達成するついでに、「前から存在は知ってたElectronを使ってみよう」ということになり、始めてみた。
ここで知り得た知識を忘れないために、個人的な独り言を含めた備忘録のようにして残しておこうと思う。当時の自分と同じような初心者の参考になったりならなかったりしてくれると嬉しい。

#環境構築
https://ics.media/entry/7298/ を参考にした。
###Node.jsの導入
https://nodejs.org/ から10.16.2LTSをインストールした。
「LTSってついていれば安定、安心じゃね？」という個人的な印象からなので別に最新版でもいいと思う。知らんけど。
###Electronの導入
適当にプロジェクトフォルダを作成して、Windows PowerShellでそのフォルダに移動。

```markdown
npm i -D electron
```
を実行し、Electronを導入する。参考サイトに従ってプロジェクトフォルダ単位での環境構築としたが、正直グローバルで導入してる記事もあり、どっちだよ！ってなってる。その後

```markdown
npm init
```
を実行し、package.jsonを生成する。なんか色々聞かれたが、Enterキーを連打して適当に生成してるけど特に問題は発生していない。

#はじめての実行
いわゆるHello Worldである。
プロジェクトフォルダの下にsrcという名前でフォルダを作り、

- index.html
- main.js
- package.json

の3つのファイルを作成する。
内容は環境構築のときと同じサイトからコピペすれば問題ないはず…だが。
いざ実行すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/7711d66c-9485-dfa3-6eec-748eb8499a79.png)

あれ？バージョン表示されてなくない？それになんかエラー出てない？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/67894619-21a5-eda4-7b1f-e97c622fe584.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/b994d6ff-faa4-2001-7d73-07989f29b03c.png)

Uncaught ReferenceError: process is not defined …? 赤線部がおかしいはずだが、どういうことなんだろう。
とりあえずググるとこんな情報が。

https://github.com/electron/electron/issues/18139#issuecomment-489137050
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/5dd2e62e-bc2c-b56b-3c9f-c656914b63de.png)

(要約：webPreferences:のとこを追加しろ)

はあ、そうですか。ふざけんじゃねえ。これだけで動くようになっちゃったよ。ありがサンキュー、GitHub。
ということで追加した際のコードはこうなった。

```javascript:main.js
//前略
function createWindow() {
  // メインウィンドウを作成します
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });
//後略
```
ただしこれが正しい解決法かは知らない。有識者のみなさん、ぜひ指摘していただけると助かります…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/610dfae3-b0c4-9ff2-6ad0-d4f506b14a05.png)

そしてなんとか動いた。(っ'ヮ'c)ｳｩｯﾋｮｵｱｱｧｱｱｱｧｲｪｲL('ω')┘三└('ω')｣ｲｪｲｲｪｲL('ω')┘三└('ω')｣ｲｪｲ
Warningが出てるけど気にしねえ。これは仕事じゃねえんだ。動けばいいんだよ、動けば。

#実際にコードを書いていくよ
自分語りをすると、HTMLとは小学2年生のころからの付き合いなので書こうと思えば書けないことはない。
問題はJavaScriptだ。正直アイツは何者なのかわからん。と、ここでグダグダ言っても無駄なので、今まで学んだ他言語での知識を借りつつ、JSについてGoogleの力を借りて調べつつ、コードを書いていく。
…調べたいことが一瞬で調べられるなんて、いい時代になったもんだよねえ。

##テキストで時刻を表示させよう
時計を作るっていうんだから、多機能時計とはいえこれがないと論外である。まずはテキストでの表示を試してみる。

```html:index.html
<!-- bodyタグの中以外は略してます -->
<body>
 <h1>時刻表示だよー(o・▽・o)</h1>
 <script>
  var time = new Date();
  var hou = time.getHours();
  var min = time.getMinutes();
  var sec = time.getSeconds();
  document.write(hou+"時"+min+"分"+sec+"秒");
 </script>
</body>
```
`var time = new Date(); `でDateオブジェクトのインスタンスを作成、それをtime変数へ代入、
それから`var hou = time.getHours();`で、timeの内容を使ってhou変数へ時刻のn時の部分を代入してるらしい。
解説を読んでも「ん、オブジェクト…？」となってるのでここは追々勉強していく必要がありそうね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/2f273407-ce67-bd55-5609-8c63778c0b54.png)

これで実行時の時間が表示される。
どうでもいいけど(o・▽・o)を多用する癖をやめたい。でもやっぱりもちょはかわいい。

###リアルタイムで表示させてみたい
やっぱり時計は「数字が動いてこそ時計」って部分があるよね。
コードをずっと実行する方法がないか調べて書いてみた。ついでに、1桁の場合は先頭を0で埋めるようにしてみた。

```html:index.html
<!-- bodyタグの中以外は略してます -->
<body>
 <h1>リアルタイム表示</h1>
 <p id="clock">とけい</p>
 <script>
  function clock() {
   var time = new Date(); 
   var hou = ('0' + String( time.getHours() )).slice(-2);
   var min = ('0' + String( time.getMinutes() )).slice(-2);
   var sec = ('0' + String( time.getSeconds() )).slice(-2);
   document.getElementById("clock").innerHTML = hou+"時"+min+"分"+sec+"秒";
  }
  setInterval('clock()',500);
 </script>
</body>
```

まずclockという関数を定義し、これの中に処理を記述していった。
`<p id="clock">`でタグにclockというidを指定、JS側でそのidがついたタグの内容を書き換える、という具合らしい。
そしてここが重要なのだがコードをずっと実行させるにはsetIntervalという関数を使うらしい。
`setInterval('clock()',500);`とすることで、clock関数を500msごとに実行することができるらしい。やったぁ!

ちなみに0埋め処理はこちらの記事を参考にした。 https://qiita.com/cress_cc/items/3e820fe1695f13793df3
ソースが短くなって良さげだったので採用。発想が新しいなと純粋に思った。

実行するとこうなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/f1c7ccd9-10e5-1fc5-5c92-44ca7f55c95a.png)
0埋めもうまくいってるらしい。

ちなみに表示部分を先ほどと同じようにdocument.write()を用いて書くとこうなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/3244c709-6e18-79eb-1b1e-5f62565e585a.png)
うわ。こりゃだめだわ。まあ予想はついてたけど、だめ。よくわからんけど0埋めもうまく行ってないし。
だからみんな、getElementByIdを用いて中身を置き換えるようにしてんだね。理解。

#画像で時計表示させたい
###まず動的に画像を変更したいよね。
HTMLタグでは

```html
<img src="img/serika_hakozaki.png">
```
のようにすると、imgフォルダ内のserika_hakozaki.pngが表示される、というのは知っている。しかしこいつをJSの力で動的に変更させたい。どうすりゃいいのか。
ということで調べてコードを書いてみた。

なおこのコードを書くにあたって、srcフォルダ内にimgフォルダを作成、そのフォルダ内に

- kotoha.jpg
- sayoko.jpg
- kaori.jpg
- mirai.jpg

を用意した。

```html:index.html
<!-- bodyタグの中以外は略してます -->
<body>
 <h1>コロコロ変わる画像</h1>
 <img src = "img/kotoha.jpg" id = "img0">
 <script>
  var img_list = new Array('kotoha.jpg','kaori.jpg','mirai.jpg','sayoko.jpg');
  function imgChange(){
   document.getElementById("img0").src = 'img/'+img_list[Math.floor(Math.random() * 4)];
  }
  setInterval('imgChange()',1000);
 </script>
</body>
```
時刻のリアルタイム表示のときと同じような感覚で書けた。
HTML部分では` <img src = "img/kotoha.jpg" id = "img0">`で普通にimgタグを指定。リアルタイム表示のときのpタグと同じようにidを指定し、JS側からそのidのついたタグのsrc要素を変更する、という感じらしい。
次にJS部分。まずファイルの名前を`img_list`という名前の配列に代入した。
次に`imgChange`という関数を定義し、その中に処理を書いた。
`document.getElementById("img0").src = 'img/'+img_list[Math.floor(Math.random() * 4)];`で`id = "img0"`のついたタグのsrc要素を書き換えるようにした。
`Math.floor(Math.random() * 4)`は乱数。`Math.random()`は0～1までの小数の乱数を生成するので、その乱数に最大数+1をかける。それから`Math.floor()`を使って値の小数部分を切り捨てることで、整数の乱数を得られる、という具合である。
この整数の乱数を用いて、配列からランダムでファイル名を呼び出している。

これを実行するとこうなる。
![image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178327/a3b088d8-26b5-bcb7-a6f4-cb64dabdf852.gif)
OK.

たまに1秒で切り替わらないことがあるが、はじき出された乱数が同じ値になったときに起こりうるものであるので、特に問題はない。はず。
乱数が被ったときの処理を書けば回避できるはずだが、これがメインじゃないのでここでは割愛。

#前編おしまい
ページの内容が増えて読者の方の読む気が失せそう＆はやく公開したいという私の勝手な理由により、後編へ続きます。