どうも、今年の夏に初めてElmをさわったので、記念としてElmアドベントカレンダーに参加しています🎄
普段はサーバーサイドエンジニア兼 ワロタグマの育成を生業としているものです。
今回は、このワロタグマがどうも小さいお子さんにウケが良い(n=1)とのことで、幼稚園においては何かと必須アイテムであった「おなまえシール」のめーかーを作ってみることにしました。
ちなみにコードは こちら です。
成果物
最近、お肌を労るために、髪にも顔にも身体にも使えるナチュナルな石鹸 を使い始めました。
これを手を洗うために使われたら辛い(手はキレイキレイで十分やろ)ので、ラベリングするためにつくりました。
つまり、おなまえシールは大人でも意味のある形で使えます。
おなまえシールのつくりかた
- おなまえシールめーかーをひらく
- おなまえシールをいい感じにデザインする
- (よしなにスクショかなんかして)マスキングテープ に印刷する
圧倒的MVP(Minimum Viable Product) 仕様です。
近々、画像に変換する機能もつけたいですね。
おなまえシールめーかーのつくりかた
elm-ui を使ってつくりました。
半年前にElmで くそゲーをつくった時、
< 「レイアウトとかで時間使いたくないよ〜〜くそゲー作りながらElmの勉強したいだけだもん〜〜でもオシャにしないとやる気下がる〜〜」
となり、その後興味本位でelm-uiをさわってみて、アイディアをサッと形にしたいときはこれでつくるのが良さそうだなと思いました。
CSSが分からなくても、なんならElmが分からなくても(TEAさえ分かれば)、カンタンにUIができる!
ということで、最短でアイディアを具体化していくことを前提として圧倒的そういうノリでelm-uiを紹介していきたいと思います。
(まずはelm-uiでできることの一覧を見たい方は リファレンス を流し読みすることをオススメします。elmのリファレンスは綺麗で読みやすくて好き。)
まずはTEA
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)にて Html Msg
で検索します。
ありました〜〜〜〜〜〜🎉
elm-uiをいつものコードに組み込むには、これを噛ませてあげれば良いっぽいですね。
そして、この子には Element msg
型とやらを渡せばいいみたいです。
これも検索してみると、っぽいのがありますね。
text
は文字列を Element msg
にしてくれる、el
はなんと div
相当のものだそう。
ということで、このように書いていきます。
view : Model -> Html Msg
view model =
layout [] <| el [] <| Element.text "おなまえシールめーかー"
まずは文字列を表示することができました🎉
要素を好きな位置に配置したい
とりあえずタイトル「おなまえシールめーかー」を真ん中に置きたい。
center
と検索してみると、っぽいのがありました🎉
- centerX: Attribute msg
- centerY: Attribute msg
- (Alignmentは他にも色々ありますね)
これらはAttribute msg型を返すので、先ほどの el
の定義をみてみると、 List (Attribute msg)
に入れてあげれば良さそう。
layout [] <| el [ centerX ] <| Element.text "おなまえシールめーかー"
真ん中に配置することができました🎉
ここまででもうelm-uiを使いこなすパターンがお分かりいただけたかと思います。
divを積み上げるような感覚でElement msg
をつくっていき、
それぞれの要素は List (Attribute msg)
というデコレーション箱を持っているので、それらに Attribute msg
型を返すものを「直接」入れていくだけでリッチになっていきます。
複数の要素を配置したい
まだタイトルしか表示できていませんから、ここから複数の要素を表示させていきたいです。
Element msg
を複数個配置したいので、 List (Element msg)
で検索してみると、
- row: List (Attribute msg) -> List (Element msg) -> Element msg
- wrappedRow: List (Attribute msg) -> List (Element msg) -> Element msg
- column: List (Attribute msg) -> List (Element msg) -> Element msg
を発見。
これらは複数個の要素を1つの Element msg
に束ねてくれるようです。
タイトルとInputを縦に並べたいので、 column
を使ってみます。
view : Model -> Html Msg
view model =
layout [] <|
column [ centerX ]
[ el [] <| Element.text "おなまえシールめーかー"
, el [] <| Element.text "ここにInput"
]
複数個の要素を縦に配置できました!
このように、縦に配置していきたいか、横に配置していきたいかを考えていれば、そんなに頭を使わずともどんどんUIが出来上がっていきます。
次に、row と Image を使って、ワロタちゃん達を横に並べてみました。
ん、なんか圧倒的に横にずれて見えないワロタちゃんがいる・・・。
そこで、wrappedRowに怪しげな表記を見つけました。
Same as row, but will wrap if it takes up too much horizontal space.
んーこれですね。
これでめでたく [とても可愛いワロタグマみにえもじ] (https://store.line.me/emojishop/product/5d2ae112040ab1e99b74afb5/en) が全員表示できました🎉
(お顔とお手手を繋げていくことでコミュニケーションが取れるこのえもじ天才的に可愛いと思いませんか?)
wrappedRowのデコレーション箱に width を入れて幅を指定することで折り返しを実現できました。
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を使うと、👆のようなデバッグモードになりデベロッパーツールを開く手間が省けてとても便利です。
ユーザーに入力させたい
Element.Input を見ていきます。
今回は一行テキスト入力フォームが欲しいので、text を使っていきます。
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 を使っていい感じにしていきます。
しくみはこういう感じです。
layout [] <|f
column [ padding 30, spacing 30, centerX ] [ ... ]
こうすることで、デザインに余白が生まれ、圧迫感が抑えられました。
色をつけたい
背景色をつけたいので、Element.Backgroundを見ていきます。
colorには Color
型を渡す必要があります。
Color
型を返す関数を探すと、結構色々あります。
今回は、
layout [ Element.Background.color (rgba255 223 107 160 100) ] <| ...
という感じで、設定してみました。
ちなみに、自分の色選びのセンスが悪いと途中でなえてくるので、私はいつも
「{ハイブランド名} パリコレ」で検索
して、イケイケコーディネートをスポイトで吸い取ってRGBに変換しています。
今回は「グッチ パリコレ」でいきました。
これで開発中に「なにこの色・・・」とならず、「これは世界的デザイナーが生み出したお色だからオシャレに違いない」と言い聞かせられます。
どぎついな。
丸をかきたい
丸はElement.Borderの rounded でかけます。
wrappedRowの中身をこうして、いい感じに変身できました。
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)
選択すると、半透明になります。
可愛い!可愛いぞ!
ここまででテンションが上がるUIができたので、
あとはmodelとupdateを書いていって、いい感じに「おなまえシール」の完成形を表示する 機能を実装していくだけです!
ちなみに、以前elm-uiを利用して一番感動したのが indexedTable だったのですが、今回はくそゲーオブくそゲーだったために使わずして完成してしまいました。。
Formが可変長だった場合に、tableの中でFormをindexedMapしたいと思うだろう?と先読みしてくれたかのようなテーブルなので「これこれ〜!」感がありました。
またの機会に記事にしよう。
最後に、印刷しよう
好きなワロタキャラを選択し、おなまえを入力して、下に表示された「おなまえシール」を最後に印刷してfinishiですね。
余談of余談ですが、マスキングテープ印刷用紙 は結構使えます。
私のPCもこんな可愛いくなっています
このめーかーを作るきっかけになったワロタ好きなお子さんにも、つくってあげよう〜〜!
それでは、2019年も残り少ないですが、毎日一切れずつシュトーレンを食べて楽しく過ごしましょう🍰良いを年を〜〜🎍