Electron, JavaScriptでアナログ時計ウィジェットを作る【Electron入門】

# Electron,JavaScriptでアナログ時計ウィジェットを作る【Electron入門】:watch:

## なぜ時計ウィジェットを？

先輩「コーディングとか集中してると時間忘れてやっちゃうよね〜」
ぼく「そうですね〜、気づいたらもうこんな時間ってなりますよね〜」
先輩「ツールバーも基本隠してるから時間わからんよね〜」
ぼく「じゃあウィジェットで時計とか置いたらいいんじゃないですか？」
先輩「Win10ってウィジェットとかあるんだっけ？」
ぼく「どうですかね〜あれだったら作りますよ」

というわけでElectron入門としてアナログ時計を作ってみよう！と思いたった私のメモ書きです。
ElectronというよりはJavaScriptでアナログ時計作ってるという感じですが・・・

## Electronの環境準備

ここは思い切って割愛させていただく。
こちらの記事が大変参考になりました。

[Electronでアプリケーションを作ってみよう - Qiita](https://qiita.com/Quramy/items/a4be32769366cfe55778)

準備を整えていざコーディング！

## まずはデジタル時計を作ってみよう

デジタル時計なら時間を画面に出力するだけなのでとっても楽ちん。
まずはデジタル時計を作ってみる。
ソースは[こちら](https://github.com/spadeloves/electron_digital_clock "spadeloves/electron_digital_clock: simple digital clock made with electron")にあります。

HTMLはこんな感じ

```index.html
<body>
	<div class="clock_wrap">
  		<p class="clock">
  			<span class="hour"></span>:<span class="minute"></span>:<span class="second"></span>
  		</p>
	</div>
</body>
```

スクリプトはこんな感じ　使い慣れているのでjQueryに頼ってしまう・・・

```JS
	$(document).ready(function(){
		$(function(){
    		setInterval(function(){
        		updateTime();
    		},1000); //１秒ごとに関数を実行
		});
	});

	/*
	 * 時間更新用関数
	 */
	function updateTime(){
		//Dataオブジェクト作成
		var time = new Date();
    //時、分、秒を取得
    	var hour = $(".hour");
    	var minute = $(".minute");
    	var second = $(".second");

    //全ての頭0埋め
	    var H = ('00' + time.getHours()).slice(-2);
	    var M = ('00' + time.getMinutes()).slice(-2);
	    var S = ('00' + time.getSeconds()).slice(-2);

    //HTMLに反映
    	hour.html(H);
    	minute.html(M);
    	second.html(S);
	}
```

おそまつな作りですが、１秒に一回更新用の関数を実行し、HTMLに反映しているだけです。
動作はこんな感じ

<img src="https://qiita-image-store.s3.amazonaws.com/0/182837/55cd33b8-2ca0-0ace-dc0b-d22547e11e62.gif" width=300>

画面録画してGif化したら時が加速した・・・実際はちゃんと1秒おきなのでOK

これでデジタル版は出来ました。
ただ今回はアナログ時計が最終目標なので、これをベースにアナログ時計を作っていきます。

## アナログ時計を作る

ソースは[こっち](https://github.com/spadeloves/electron_analog_clock "spadeloves/electron_analog_clock: simple analog clock made with electron")にあります。

### ウィンドウを丸くしたい

デジタル時計のときは気にしていませんでしたが、アナログ時計にするならウィンドウが丸くならないとカッコ悪い！
ということで、ElectronのWindowに```transparent ```の設定を加えます。

```main.js
mainWindow = new BrowserWindow({width: 302, height: 302, frame:false,resizable:false,transparent: true});
```

### ロジックの考え方

考え方としては、背景、長針、短針、秒針の４つのレイヤーを用意し、それぞれを時間に応じて回すことでアナログ時計を表現しようと思います。
イメージとしてはこんな感じ

<img src="https://qiita-image-store.s3.amazonaws.com/0/182837/a32a5ecd-17f5-3015-d461-809c60fc4a4a.png" width=500>

### HTML,CSSに落とし込む

まずHTMLは単純にこうしました。
針の画像を作成するのが面倒なので、とりあえず文字を置いてます。

```index.html
<body>
	<div class="clock_wrap">
		<div class="clock_parts clock_back_ground"></div>
  		<div class="hour clock_parts"><br><br><br>H<br>H<br>H<br>H<br>H</div>
		<div class="minute clock_parts">M<br>M<br>M<br>M<br>M<br>M<br>M<br>M</div>
		<div class="second clock_parts">S<br>S<br>S<br>S<br>S<br>S<br>S<br>S</div>
	</div>
</body>
```

CSSはこんなかんじ

```clock.css
.clock_back_ground{
	border: 1px solid;
	border-radius: 200px;
	border-color: #aa00aa;
	background-color: #fff;
}

.clock_wrap{
	text-align: center;
	width: 100%;
}

body{
	margin: 0;
    -webkit-app-region: drag;
    height: 300px;
    overflow: hidden;
    -webkit-user-select: none;
}

.clock_parts{
	position: absolute;
	width: 300px;
	height: 300px;
}

.hour{
	z-index: 1;
}
.minute{
	z-index: 2;
}
.second{
	z-index: 3;
}
```

これでとりあえずこうなります。

<img width="326" alt="スクリーンショット 2018-05-12 16.12.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/182837/a3fb2ad2-67d5-e78a-c8f2-11c303a91855.png">

そこ、ダサいとか言わない。
あとは、針のレイヤーを時間に合わせて回転させれば、基本的な動作は完成します。

### 針のレイヤーを回転させる

時間の取得まではデジタルと同じです。

```JS
	function updateTime(){
		var time = new Date();
	    var H = time.getHours();
	    var M = time.getMinutes();
	    var S = time.getSeconds();
```

取得した時間の値を元に、回転角度を割り出します。

* 短針の回転角度
  *  360 / 12 * 時
* 長針の回転角度
  * 360 / 60 * 分
* 秒針の回転角度
  * 360 / 60 * 秒

これをソースに落とし込むとこうなります。

```JS
	    var HRotate = 360/12*H;//短針
	    var MRotate = 360/60*M;//長針
	    var SRotate = 360/60*S;//秒針

	    rotateClock(HRotate,MRotate,SRotate);//回転角度を反映する関数
```

反映する際は以下のようになります。
ElectronはChromiumで動いているので、単純に```transform```ではなく、```-webkit-transform```で回転角度を設定します。

```JS
	function rotateClock(HRotate,MRotate,SRotate){
		var hourDOM = $('.hour')
		var minDOM = $('.minute')
		var secDOM = $('.second')

		hourDOM.css("-webkit-transform", "rotate("+HRotate+"deg)");
		minDOM.css("-webkit-transform", "rotate("+MRotate+"deg)");
		secDOM.css("-webkit-transform", "rotate("+SRotate+"deg)");
  }
```

これで基本的な実装は完成です。
実際の動作がこんな感じになっています。

![analog.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/182837/321b3168-37b4-04d3-c643-1b66c58ffbe6.gif)
それなりに時計っぽくなりました。

## 課題

- [ ] 短針が１時間に一回しか動かない:alarm_clock:
よりリアルなアナログ時計にするには少しずつ短針を動かす必要がある。
1時間ごとの角度は30度なので、```30/60 * 分```を短針の角度に足してあげればいいかも。

- [ ] 背景の表示がないので、何時かすぐにわからない:open_mouth:
そこは普通に画像か何かで準備して背景に当ててやればいいかと思います。~~画像作るのがめんどい~~:stuck_out_tongue:

- [ ] 大きさがでかい、というか自由に変えれるようにしろ:japanese_goblin:
300px * 300pxで固定されているので、レスポンシブにする改良が必要…
CSSはあんまり得意じゃないので誰か助けて…:dizzy_face:

## まとめ
なんだかElectronというよりはJavaScriptでどうやってアナログ時計作るか、みたいな話になってしまいました・・・
アナログ時計をWebで表示したいときにも普通に使えるので良しとします。
レスポンシブの課題は**致命的**ですね。~~誰か手伝って~~:cry:

カスタマイズの機能をもたせてもっと使いやすいシンプルな時計にしていきたいです。
その時はまた記事を上げます。