1
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

[Elm] elm-touch-events使ってみた

最近、elm-touch-eventsを使って遊んでみてるので、その簡単な解説をば。

elm-touch-eventsとは

Elmには、デフォルトでタッチイベントを制御する機能は入っていません(Elm 0.18では)。
これでは、スマホ向けに凝ったUIを作るときに、困ったりすることがありそうですね。

そこで便利なpackageが、elm-touch-eventsです。

何ができるの?

DOMをタッチしたときに、「指が触れたとき」、「指を動かしたとき」、「指を離したとき」の3つについて、
それぞれに発火するイベントを作成することができます。
マルチタッチにも対応しています。

デモ

スライド動作によるオブジェクトの移動と、
ピンチアウトによるズーム機能を実装しました。
https://ebiryu.github.io/elm-touch-demo/
(※スマホなどのタッチデバイスじゃないと動作しないです)

使い方

大体のことはpackageのページを見れば書いてありますが、
今回は日本語のドキュメントを増やす意味で書いておきます。

インストール

elm-packageでインストールします。

elm-package install mpizenberg/elm-touch-events

SingleTouch

マルチタッチにも対応していると言いましたが、
シングルタッチはもっと簡単に実装できます。

デモのソースコードを見てみましょう。
https://github.com/ebiryu/elm-touch-demo/blob/master/src/Main.elm

まずはviewから。

objects : Model -> List (Svg Msg)
objects model =
    [
    ...
    , polygon
        [ SingleTouch.onStart SingleStart
        , SingleTouch.onMove SingleMove
        ...
        ]
        []
    ]

このobjectsはviewで読み込んでるsvgの要素ですが、
その中の一つの三角形に、attributeとしてonStartonMoveを追加しています。

このonStartonMoveは、HtmlのEventsのonInputのようなものです。
onInputでは、StringをMsgと一緒に返していますが、
onStartonMoveでは、DOM全体から見たときのタッチした座標をMsgに乗せて返します。

Msgは次のようになります。

type Msg
    = SingleStart Touch.Coordinates
    | SingleMove Touch.Coordinates
    | ...

Touch.Coordinateは、{clientX : Float, clientY : Float}という形になっているため、あとはこれらの値をupdate内で使ってあげればいい感じになります。

MultiTouch

MultiTouchでも、同様にonStartonMoveなどがあるのですが、SingleTouchとは違い、Touch.Coordinatesではなく、Touch.Eventを返します。

view : Model -> Html Msg
view model =
    div
        [ ...
        , MultiTouch.onStart MultiStart
        , MultiTouch.onMove MultiMove
        ]
        [ ...
        ]
type Msg
    = ...
    | MultiStart Touch.Event
    | MultiMove Touch.Event

このTouch.Eventは、そのままでは扱いづらいので、これを処理する関数もpackageに同梱されています。
それは、Touch.touchesTouch.changedTouchesTouch.targetTouchesの3つです。

これらについて詳細は、次のページに書いてあります。
https://www.html5rocks.com/ja/mobile/touch/
touches: 現在画面上にあるすべての指のリスト。
targetTouches: 現在の DOM 要素上にある指のリスト。
changedTouches: 現在のイベントに関与している指のリスト。たとえば、touchend イベントでは、離れた指のリストになります。

これら3つの関数は、指のリストをDict型で返します。
デモでは、次のように、Dict.valuesでList型に変換して使っています。

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ...

        MultiStart event ->
            let
                ...

                eventPositions =
                    Dict.values <| Touch.touches event

                ...
            in
                ...

        MultiMove event ->
            let
                ...

                eventPositions =
                    Dict.values <| Touch.changedTouches event

                ...
            in
                ...

こんな感じですね。
基本的には、指が触れたときにtouchesでその全部の指の位置を取り値を初期化し、
動いたときにもtouches、離したときその座標を取りたいときはchangedTouchesを使う感じになりそうです。

svgの移動やズームに使っているtransformについては、以下のページがとても参考になりました。
http://defghi1977.html.xdomain.jp/tech/svgMemo/svgMemo_04.htm

まとめ

elm-touch-eventsを使えば、スマホ向けのリッチなwebアプリもElmで作れそうですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?