【Fuse】UXマークアップをより強力に！UX Reactive Expressions

[UX Reactive Expressions](https://www.fusetools.com/docs/ux-markup/expressions)（以降、UX表現式）は、Fusetools（以降、Fuse）V0.31から新たに追加された機能です。

実験的な機能のため、サイトには以下のように注意書きがありますので必ず目を通しておきましょう。

> Note that UX expressions is an experimental feature and is subject to change. If you're using this in UX markup, please keep an eye on the changelog when updating. If you're using this feature from Uno, be aware that several large API changes are planned.

> [和訳]UX表現式は実験的な機能で変更される可能性があります。UX Markupにこれを利用する場合は、アップデート時の変更内容（changelog）をご確認ください。Unoでこの機能を利用する場合は、API変更もあり得ることにご注意ください。



## バインディング（Bindings）

リファレンスには以下の3つの使い方があります。

- データのバインディング（Data bindings）
	- `{path.to.data}`
- 属性のバインディング（Property bindings）
	- `{Property someObject.SomeProperty}` または `{Property SomeProperty}`
- リソースのバインディング（Resource bindings）
	- `{Resource resourceKey}`

ここで取得した値を元に「算術」「ベクトル」「文字列やテキスト」を反映することができます。
それではそれぞれの使い方を紹介します。




## 算術（Arithmetic）

UX表現式は、単位（％やpxなど）の有無にかかわらず加算（+）、減算（-）、乗算（*）および除算（/）することができます。
	
```xml:sample01.ux
<App>
	
<!-- StackPanelのローカル名を「panel」と指定 -->
<StackPanel ux:Name="panel" Width="100%">

	<!--
	    Rectangleのローカル名を「rect」に指定
	    Widthを「panel」のWidthの半分に指定
	-->
	<Rectangle ux:Name="rect" 
		Width="width(panel) / 2"
		Height="40" Color="Red" Margin="5" />

	<!-- Widthを「rect」のWidthの半分に指定 -->
	<Rectangle
		Width="width(rect) / 2"
		Height="40" Color="Blue" Margin="5" />

</StackPanel>
</App>
```

以下のように赤い四角は画面幅の半分（50%）に、青い四角はさらに赤い四角幅の半分（25%）に指定されます。

![FuseReactiveExp_001.gif](https://qiita-image-store.s3.amazonaws.com/0/155997/671f2700-8431-d73b-e24f-c60af74341d0.gif)


## ベクトル（Vectors）

カンマ（,）を使ってベクトル（最大4つまで）が構成できます。

```xml:sample02.ux
<App>
<StackPanel>

    <!-- Sliderのローカル名を「slider」に指定 -->
    <Slider ux:Name="slider" />

    <!-- PanelのPadding属性のベクトルにsliderの値をリアルタイムで反映 -->
    <Panel Padding="10, {Property slider.Value}, 10, {Property slider.Value} / 2">
        <Rectangle Color="#FFCC00" Width="100%" Height="30" />
    </Panel>

</StackPanel>
</App>
```

![FuseReactiveExp_002.gif](https://qiita-image-store.s3.amazonaws.com/0/155997/913624e1-8c02-686b-eeb9-1f57f3061f2b.gif)


ベクトルは以下のようなルールができようされます。

- 最初から「Left, Top, Right, Bottom」
- X -> XXXX
- XY -> XYXY
- XYZ -> XYZ1



## 文字列とテキスト（Strings and text）

```xml:sample03.ux
<App>
<StackPanel Padding="10">
		
	<!-- Sliderのローカル名を「slider」と指定 -->
	<Slider ux:Name="slider" />

	<!-- 「slider」と指定された要素の値をリアルタイムで反映 -->
	<Text Value="{Property slider.Value}" Alignment="TopCenter" />
	
</StackPanel>
</App>
```

以下のようにSliderのハンドラーを動かすと、値の変化がリアルタイムでTextに反映されます。

![FuseReactiveExp_003.gif](https://qiita-image-store.s3.amazonaws.com/0/155997/57ebd21b-2aeb-f56c-0f01-294c7b7aef75.gif)



## UX表現式で利用できる関数（Functions）

また、UX表現式には以下のような関数を組み合わせることもできます。

- max(a, b) : 二つの数字の中で、大きい値を返す
- min(a, b) : 二つの数字野中で、小さい値を返す
- toLowers(s) : 渡された英字の小文字に返す
- toUppers(s) : 渡された英字の大文字に返す
- width(element) : 他のUX要素の配置した結果を元に横幅を返す
- height(element) : 他のUX要素の配置した結果を元に縦幅を返す
- spring(value) : valueの数値に対してバネの物理演算を実施する

```xml:sample04.ux
<App>
<DockPanel>

    <Grid Rows="auto, 5*, 5*">

	<!-- Sliderに関連する要素を生成 -->
	<Grid Columns="1*,7.5*,1.5*"　Color="#333" Padding="10">
	    <Text Value="0%" Alignment="CenterLeft" Color="#DDD" />
	    <Slider ux:Name="slider" Value="1" Minimum="0" Maximum="1" />
	    <Text Value="100%" Alignment="CenterRight" Color="#DDD" />
	</Grid>


	<!-- Alphaに関連する要素を生成 -->
	<Grid Columns="2*,8*" Color="#DDDDDD" Padding="10" Margin="5">
	    <Text Value="Alpha" Alignment="VerticalCenter" />
	    <!--
		max(a,b) : sliderの値と0.5中に大きい値を透明度に適用
	    -->
	    <Rectangle 
		Opacity="max({Property slider.Value}, 0.5)" 
		Width="100%" Height="100%" Color="#4894E5" />
	</Grid>

	<!-- Scaleに関連する要素を生成 -->
	<Grid Columns="2*,8*" Color="#DDDDDD" Padding="10" Margin="5">
	    <Text Value="Scale" Alignment="VerticalCenter" />
	    <!--
		四角の中心を基準にサイズが変わるように Anchor(50%, 50%)を制定
		max(a,b) : sliderの値と0.5中に大きい値 * 100%を横幅と縦幅に適用
	    -->
	    <Rectangle 
		Anchor="50%, 50%" 
		Width="spring(max({Property slider.Value}, 0.5)) * 100%" 
		Height="spring(max({Property slider.Value},0.5)) * 100%" 
		Color="#CC0000" />
	</Grid>

    </Grid>


</DockPanel>
</App>
```

![FuseReactiveExp_004.gif](https://qiita-image-store.s3.amazonaws.com/0/155997/2814bff9-0f9e-c7fa-cf4b-b0e3e90bd0ef.gif)

※青い四角の透明度と赤い四角の大きさは50%以下は変化しません。

このようにUX表現式を利用すると、UI Markup上で属性をつけて変数扱いしたり、リアルタイムでデータや属性の値を他のUX要素に反映することができるので、効率の良いコードが書けるようになります。
今後、どのような方向で拡張されるか楽しみです！