Noodlで自作のUIを作成する

## 概要
[「MQTT通信を使った呼出システムを構築する」](https://qiita.com/macole/items/03787c863c990756aee4)として、M5StackとNoodlを使った自作の呼出システムを紹介しました。その中では細かな説明をしきれなかったので、今回は解説編としてNoodlでのUI作成について説明します。

### 目次
1. Noodlでの独自UI作成手順
2. 独自UIの事例

### サンプルデータ
- [Github](https://github.com/macole/macole.github.io/tree/master/Noodl2_UIDemo
)：プロジェクトデータ
- [デモサイト](https://macole.github.io/Noodl2_UIDemo/index.html)

## 1. Noodlでの独自UI作成手順
3色信号機を例にUI作成手順を説明します。
この信号機は、受信したMQTTメッセージ「正常・呼出し・異常」に応じて「緑・黄・赤」のランプを点灯させる機能を持ちます。完成後は下のようになります。

**3色信号機**
![3LightSignal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/745d4776-11d4-3dcc-c5e1-a05f750bba3e.gif)

## 信号の作成
3色信号機を作る前に、その部品となるLight部分を作ります。Lightは外部から「点灯：ON,消灯：OFF,点滅:flashing」信号を受取り、その状態でライトを点灯するコンポーネントです。

まずは
・Componentを新たに選択します。
Componentの中に
・ベースとなるGroupを作成します。

![img0046_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/47187326-dcf7-84e1-ee45-aa54c540cb3d.png)

### ①信号表示：ライト部分をGroupで作成します。
ライトがついていない状態、ライトがついている状態の2つをGroupで作成しています。
2つのGroupを重ねているのは、信号機が消えるときにボワーっと光るイメージにするためで、
一方をサイズを大きくしながら徐々に透明にすることで残像を残しながら消えてゆく様に見せています。

### ②LED状態：ON/OFFの状態をStatusノードで作ります
Statusノードは状態と、その状態に対応するVaruleを設定します。ここでGroupのプロパティを
設定しています。

|状態|イメージ|opacity|size(%)|
|:-:|:--|:-:|:-:|
|ON|赤色となる|1|90|
|Off|少し大きめに、消えていく|0|100|

### ③入力された状態の保持
外部から入力された状態の保持。②LEDの状態を変化させる。タイマーを起動するために
Statesを利用しています。

- ON：点灯＋タイマーを止める
- OFF:消灯＋タイマーを止める
- 点滅：タイマーを起動してON/OFFを繰り返す

### ④点滅用タイマー
Timerを2つ重ねて1秒ごとに点灯・点滅を繰り返す無限ループを作ります。

### 入出力部分の作成
ComponentInputで色・ON/OFF信号を入力値としています

## 3色信号(制御部分)の作成
次に、Lightを3つならべた3色信号機を3LightSignalとして作成します。

![img0045_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/581ff2b2-a0c8-64f0-e5f8-b8ad85291739.png)

### ①ビジュアル部：3色信号
ベースとするGroupの下に3つのLightコンポーネントを配置しています。
LightはOn/Offの色を個別に設定できるので、好きな色に変えることもできます。

### ②信号制御部
制御部はJavascriptノードで作成しました。
入力値によって各制御をします。

|状態|信号制御|
|:-:|:--|
|異常|赤：点滅、黄：OFF、緑：OFF|
|呼出|赤：OFF、黄：点滅、緑：OFF|
|正常|赤：OFF、黄：OFF、緑：ON|

Javascriptのコードを下記に示します

```javascript:制御部分
define({
	// The input ports of the Javascript node, name of input and type
	inputs:{
	    // ExampleInput:'number',
	    // Available types are 'number', 'string', 'boolean', 'color' and 'signal',
	    mySignal:'signal',
	    msg:'string',
	},
	
	// The output ports of the Javascript node, name of output and type
	outputs:{
	    // ExampleOutput:'string',
	    RSignal:'string',
	    YSignal:'string',
	    GSignal:'string',

	},
	
	// All signal inputs need their own function with the corresponding name that
	// will be run when a signal is received on the input.
	mySignal:function(inputs,outputs) {
		// ...
		//inputs.msg;
	},
	
	// This function will be called when any of the inputs have changed
	change:function(inputs,outputs) {
		// ...
		console.log(inputs.msg);
		outputs.RSignal="off";
		outputs.YSignal="off";
		outputs.GSignal="off";
		if(inputs.msg=="PressA"){
		  //console.log("Alarm");
		  outputs.RSignal="flashing";
		  outputs.YSignal="off";
		  outputs.GSignal="off";
		};
		if(inputs.msg=="PressB"){
		  //console.log("Attention");
		  outputs.RSignal="off";
		  outputs.YSignal="flashing";
		  outputs.GSignal="off";
		};
		if(inputs.msg=="PressC"){
		  //console.log("Normal");
		  outputs.RSignal="off";
		  outputs.YSignal="off";
		  outputs.GSignal="on";
		};

	}
})

```

### ③信号入力
コンポーネントとして再利用できるように、外部信号をComponentInputsノードで受取ります。
「+Port」でInputsを作成します。ここでは「msg」としました。

これで出来上がり。
後はStatusのValueで色やタイミングを調整して完成です。

## 2.独自UIの事例
同様な手順で様々なUIを作成してみました。独自UI作成の参考にしてみてください。
それぞれのUIはComponentとして作成しているので、自身のProjectにLibraryとしてインポートして再利用することも可能です。

![Noodl2UI.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/0042fc4a-5d5f-3adc-2c15-aff20ce9e205.gif)

|Component|機能・備考|
|:-:|:--|
|3LightSignal|3色信号機。Lightを使用しているためインポートが必要|
|Radiobox|ラジオボックス|
|Button_onoff|On/Offボタン|
|Button_3icon|アイコンが飛び出すボタン|
|Button_toggle|大きなラジオボックス風ボタン|
|Silder_box|数値選択スライダー|
|Slider_color|色選択用のスライダ|
|GaugeCircle|ゲージメータ|
Avator|M5Stack風アバータ。Messageを使用しているためインポートが必要|
|MovableBox|カード風スイッチ。左右でマル・バツを選択|

## 3. まとめ
NoodlはStatesノードを使うことで、状態変化を持つこと。また状態に対応したプロパティを持てること。Stateに応じてプロパティを変更したときに、自動でアニメーション化してくれる機能があること。作成したUIはComponentとして再利用できること。出来上がったアプリはhtml、Javascriptとしてexportできること。
など、自身のプロトタイプに独自UI/UXを手軽に実装する手助けになってくれます。