とてもたのしいelm-uiで「おなまえシールめーかー」をつくった🎄

どうも、今年の夏に初めてElmをさわったので、記念としてElmアドベントカレンダーに参加しています🎄
普段はサーバーサイドエンジニア兼 [ワロタグマ](https://store.line.me/stickershop/product/1387437)の育成を生業としているものです。
今回は、このワロタグマがどうも小さいお子さんにウケが良い（n=1）とのことで、幼稚園においては何かと必須アイテムであった「おなまえシール」のめーかーを作ってみることにしました。
ちなみにコードは [こちら](https://github.com/natsumisawa/onamae-seal-maker) です。

# 成果物
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/ab70127f-ba43-4364-1e47-6fc62ea9c17e.gif)
:point_down:
![iOS の画像 (4).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/75b591db-4463-ba35-267f-4a4dbd52b196.jpeg)


最近、お肌を労るために、[髪にも顔にも身体にも使えるナチュナルな石鹸](https://www.moonsoap.com/SHOP/1017891/list.html) を使い始めました。
これを手を洗うために使われたら辛い（手はキレイキレイで十分やろ）ので、ラベリングするためにつくりました。
つまり、おなまえシールは大人でも意味のある形で使えます。

# おなまえシールのつくりかた
1. [おなまえシールめーかー](https://sad-lumiere-7132c9.netlify.com/)をひらく
2. おなまえシールをいい感じにデザインする
3. （よしなにスクショかなんかして）[マスキングテープ](https://www.amazon.co.jp/%E3%82%A8%E3%83%AC%E3%82%B3%E3%83%A0-%E3%83%A9%E3%83%99%E3%83%AB%E3%82%B7%E3%83%BC%E3%83%AB-%E3%83%8E%E3%83%BC%E3%82%AB%E3%83%83%E3%83%88-%E3%83%9E%E3%82%B9%E3%82%AD%E3%83%B3%E3%82%AF%E3%83%86%E3%83%BC%E3%83%97-EDT-MTA4/dp/B00B3NGHF0/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%83%9E%E3%82%B9%E3%82%AD%E3%83%B3%E3%82%B0%E3%83%86%E3%83%BC%E3%83%97+A4&qid=1575683567&sr=8-4) に印刷する

圧倒的MVP(Minimum Viable Product) 仕様です。
近々、画像に変換する機能もつけたいですね。

# おなまえシールめーかーのつくりかた
[elm-ui](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/)  を使ってつくりました。

半年前にElmで [くそゲー](https://goofy-fermi-86e26a.netlify.com/)をつくった時、

:girl: < 「レイアウトとかで時間使いたくないよ〜〜くそゲー作りながらElmの勉強したいだけだもん〜〜でもオシャにしないとやる気下がる〜〜」

となり、その後興味本位でelm-uiをさわってみて、アイディアをサッと形にしたいときはこれでつくるのが良さそうだなと思いました。
CSSが分からなくても、なんならElmが分からなくても（[TEA](https://guide.elm-lang.jp/architecture/)さえ分かれば）、カンタンにUIができる！

ということで、最短でアイディアを具体化していくことを前提として圧倒的そういうノリでelm-uiを紹介していきたいと思います。
（まずはelm-uiでできることの一覧を見たい方は [リファレンス](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/) を流し読みすることをオススメします。elmのリファレンスは綺麗で読みやすくて好き。）

## まずはTEA
```elm

type alias Model =
    { name : String }


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    let
        { name } =
            model
    in
    case msg of
        InputName n ->
            ( { model | name = n }, Cmd.none )


view : Model -> Html Msg
view model =
   div []
        [ Html.text "タイトル" ]
    -- この辺にOnInputを入れることになりそう
```

こんな感じで、おなまえを入力するための土台作りをします。

## elm-uiでviewをくみたてる
上記のview関数を、elm-uiを使ってリッチにしていきます。
ということはまず我々は、`Html Msg` 型を返す関数をリファレンスから探す必要がありそうです。

### elm-uiを組み込む土台をつくりたい
小さく小さく作っていきましょう。
`Html Msg` 型を返す関数が欲しいので、[リファレンス(Element)](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element)にて `Html Msg`で検索します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/f0f6b668-9afe-ebd9-1940-7cfbae3a9886.png)
ありました〜〜〜〜〜〜🎉
elm-uiをいつものコードに組み込むには、これを噛ませてあげれば良いっぽいですね。


そして、この子には `Element msg` 型とやらを渡せばいいみたいです。
これも検索してみると、っぽいのがありますね。

- [text: String -> Element msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#text)
- [el: List (Attribute msg) -> Element msg -> Element msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#el)

`text` は文字列を `Element msg` にしてくれる、`el` はなんと `div` 相当のものだそう。

ということで、このように書いていきます。

```elm
view : Model -> Html Msg
view model =
    layout [] <| el [] <| Element.text "おなまえシールめーかー"
```

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133373332322f33326562376131612d323338352d373539622d656464392d3033633534613334383136372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/ba6eef85-317d-e6df-95b8-b6fab66963c2.png)

まずは文字列を表示することができました🎉

### 要素を好きな位置に配置したい
とりあえずタイトル「おなまえシールめーかー」を真ん中に置きたい。
`center` と検索してみると、っぽいのがありました🎉

- [centerX: Attribute msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#centerX)
- [centerY: Attribute msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#centerY)
- （Alignmentは他にも色々ありますね）


これらはAttribute msg型を返すので、先ほどの `el` の定義をみてみると、 `List (Attribute msg)` に入れてあげれば良さそう。

```elm
layout [] <| el [ centerX ] <| Element.text "おなまえシールめーかー"
```

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3133373332322f35343936653761612d613465322d336435622d346266362d6436613538633336323333352e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/2f034292-65a5-7532-741c-76b3f8154139.png)

真ん中に配置することができました🎉

ここまででもうelm-uiを使いこなすパターンがお分かりいただけたかと思います。
divを積み上げるような感覚で`Element msg` をつくっていき、
それぞれの要素は `List (Attribute msg)` というデコレーション箱を持っているので、それらに `Attribute msg` 型を返すものを「直接」入れていくだけでリッチになっていきます。

### 複数の要素を配置したい
まだタイトルしか表示できていませんから、ここから複数の要素を表示させていきたいです。
`Element msg` を複数個配置したいので、 `List (Element msg)`で検索してみると、

- [row: List (Attribute msg) -> List (Element msg) -> Element msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#row)
- [wrappedRow: List (Attribute msg) -> List (Element msg) -> Element msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#wrappedRow)
- [column: List (Attribute msg) -> List (Element msg) -> Element msg](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#column)

を発見。
これらは複数個の要素を1つの `Element msg` に束ねてくれるようです。
タイトルとInputを縦に並べたいので、 `column` を使ってみます。

```elm

view : Model -> Html Msg
view model =
    layout [] <|
        column [ centerX ]
            [ el [] <| Element.text "おなまえシールめーかー"
            , el [] <| Element.text "ここにInput"
            ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/ef103ef2-025d-afb8-5395-142bc7be3b00.png)

複数個の要素を縦に配置できました！
このように、縦に配置していきたいか、横に配置していきたいかを考えていれば、そんなに頭を使わずともどんどんUIが出来上がっていきます。

次に、[row](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#row) と [Image](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#image) を使って、ワロタちゃん達を横に並べてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/7a2ae694-d027-582c-4993-67834e3ceb02.png)

ん、なんか圧倒的に横にずれて見えないワロタちゃんがいる・・・。
そこで、[wrappedRow](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#wrappedRow)に怪しげな表記を見つけました。

> Same as row, but will wrap if it takes up too much horizontal space.

んーこれですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/6e0bfa82-171b-7f4d-8491-42bc501a59da.png)

これでめでたく [とても可愛いワロタグマみにえもじ] (https://store.line.me/emojishop/product/5d2ae112040ab1e99b74afb5/en) が全員表示できました🎉
（お顔とお手手を繋げていくことでコミュニケーションが取れるこのえもじ天才的に可愛いと思いませんか？）

wrappedRowのデコレーション箱に [width](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#width) を入れて幅を指定することで折り返しを実現できました。

```elm
view : Model -> Html Msg
view model =
    layout [] <|
        column [ centerX ]
            [ el [] <| Element.text "おなまえシールめーかー"
            , el [] <| Element.text "ここにInput"
            , wrappedRow [ Element.explain Debug.todo, width (px 420) ] <|
                List.map
                    (\i ->
                        el
                            []
                        <|
                            image
                                [ width <| px 50 ]
                                { src = "assets/" ++ String.fromInt i ++ ".PNG"
                                , description = ""
                                }
                    )
                    (List.range 1 21)
            ]
```

ちなみに、[explain](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#explain)を使うと、👆のようなデバッグモードになりデベロッパーツールを開く手間が省けてとても便利です。

### ユーザーに入力させたい
[Element.Input](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#Placeholder) を見ていきます。
今回は一行テキスト入力フォームが欲しいので、[text](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#text) を使っていきます。

いい感じのフォームが組み込まれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/f315fdf2-80d5-67e0-3bd8-5656819ed3a9.png)

```elm
column [ centerX ]
            [ el [] <| Element.text "おなまえシールめーかー"
            , el [] <|
                Element.Input.text
                    [ width (px 400), centerX ]
                    { onChange = \n -> InputName n
                    , text = name
                    , placeholder = Just <| placeholder [] (Element.text "おなまえ")
                    , label = labelHidden "name"
                    }
```

## いい感じにデコレーションする（Attribute msgで遊ぶ）
### 余白をつくりたい
まずはpadding, margin相当の [Padding and Spacing](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#padding) を使っていい感じにしていきます。
しくみはこういう感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/f72e98d2-2383-5b5b-f394-0b7df6dd87af.png)

```elm
layout [] <|f
        column [ padding 30, spacing 30, centerX ] [ ... ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/afdbfcc8-512f-fb88-1201-5c75a32f1e4e.png)

こうすることで、デザインに余白が生まれ、圧迫感が抑えられました。

### 色をつけたい
背景色をつけたいので、[Element.Background](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element-Background)を見ていきます。
colorには `Color` 型を渡す必要があります。
`Color` 型を返す関数を探すと、[結構色々](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#rgba)あります。

今回は、 

```elm
layout [ Element.Background.color (rgba255 223 107 160 100) ] <| ...
```
という感じで、設定してみました。
ちなみに、自分の色選びのセンスが悪いと途中でなえてくるので、私はいつも
`「{ハイブランド名} パリコレ」で検索`
して、イケイケコーディネートをスポイトで吸い取ってRGBに変換しています。
今回は「グッチ パリコレ」でいきました。
これで開発中に「なにこの色・・・」とならず、「これは世界的デザイナーが生み出したお色だからオシャレに違いない」と言い聞かせられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/329a1ab6-927b-099a-156f-30e0a69886b9.png)

どぎついな。

### 丸をかきたい
丸はElement.Borderの [rounded](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element-Border#rounded) でかけます。

wrappedRowの中身をこうして、いい感じに変身できました。

```elm
wrappedRow [ spacing 5, width (px 470) ] <|
                List.map
                    (\i ->
                        el
                            [ rounded 50
                            , padding 5
                            , Element.Background.color white
                            , onClick <| OnClickButton i
                            ]
                        <|
                            image
                                [ width <| px 50
                                , if clickedIndexList |> List.member i then
                                    alpha 0.5

                                  else
                                    alpha 1
                                ]
                                { src = "assets/" ++ String.fromInt i ++ ".PNG"
                                , description = ""
                                }
                    )
                    (List.range 1 21)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/6c4deab1-8e8a-880b-40f1-f54c42554caf.png)

選択すると、[半透明](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#alpha)になります。
可愛い！可愛いぞ！

ここまででテンションが上がるUIができたので、
あとはmodelとupdateを書いていって、いい感じに「おなまえシール」の完成形を表示する  機能を実装していくだけです！

ちなみに、以前elm-uiを利用して一番感動したのが [indexedTable](https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.5/Element#indexedTable) だったのですが、今回はくそゲーオブくそゲーだったために使わずして完成してしまいました。。
Formが可変長だった場合に、tableの中でFormをindexedMapしたいと思うだろう？と先読みしてくれたかのようなテーブルなので「これこれ〜！」感がありました。
またの機会に記事にしよう。

## 最後に、印刷しよう
好きなワロタキャラを選択し、おなまえを入力して、下に表示された「おなまえシール」を最後に印刷してfinishiですね。

余談of余談ですが、[マスキングテープ印刷用紙](https://www.amazon.co.jp/%E3%82%A8%E3%83%AC%E3%82%B3%E3%83%A0-%E3%83%A9%E3%83%99%E3%83%AB%E3%82%B7%E3%83%BC%E3%83%AB-%E3%83%8E%E3%83%BC%E3%82%AB%E3%83%83%E3%83%88-%E3%83%9E%E3%82%B9%E3%82%AD%E3%83%B3%E3%82%AF%E3%83%86%E3%83%BC%E3%83%97-EDT-MTA4/dp/B00B3NGHF0/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%83%9E%E3%82%B9%E3%82%AD%E3%83%B3%E3%82%B0%E3%83%86%E3%83%BC%E3%83%97+A4&qid=1575683567&sr=8-4) は結構使えます。
私のPCもこんな可愛いくなっています :girl:

![iOS の画像 (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137322/702e617c-d1c1-d63d-8ea6-1ca3d2650448.jpeg)

このめーかーを作るきっかけになったワロタ好きなお子さんにも、つくってあげよう〜〜！

それでは、2019年も残り少ないですが、毎日一切れずつシュトーレンを食べて楽しく過ごしましょう🍰良いを年を〜〜🎍