【JavaScript】初心者でもわかるタッチイベント(touch event)

この記事では、スマートフォンやタブレット等によるタッチ操作をJavaScriptで取り扱うことができるtouchイベントについて、できるだけ簡単に解説します。

Web上に丁寧な記事はいくつもあったんだけど、正直、初心者プログラマーの僕には難しかった・・・。

執筆者も初心者で最近悩んだばかりだから、初心者の気持ちになった記事にできているかも・・・??

(簡単にするために、ちょっと大雑把な説明になります)

タッチイベントの種類

ユーザーが、画面をタッチで操作すると、操作の内容によって、以下のようなイベントが発生します。

イベント発生するタイミング
touchstartタッチ面に指が触れた時
touchendタッチしていた指を離した時
touchmoveタッチしながら指を移動させた時
touchcancel何らかの理由でタッチが取り消された時

まずは、下記のサンプルで、タッチイベント発生のイメージをつかんでください。

*touch areaに指を触れたり、離したり、動かしたりすると、発生したイベントと時刻がdisplay areaに表示されます。

touch area

display area

このデモのソースコードは下記のとおりです。

<div id="container1">
    <p>touch area</p>
    <div id="touch-area1"></div>
    <p>display area</p>
    <div id="display-area1"></div>
</div>
<script>
    const displayArea1 = document.getElementById("display-area1")
    const touchArea1 = document.getElementById("touch-area1")

    // touchstartイベント
    touchArea1.addEventListener("touchstart", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchstart"
    })

    // touchendイベント
    touchArea1.addEventListener("touchend", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchend"
    })

    // touchmoveイベント
    touchArea1.addEventListener("touchmove", () => {
        event.preventDefault();  // 画面スクロールを防止
        displayArea1.innerHTML = getTimeStamp() + " touchmove"
    })

    // touchcancelイベント
    touchArea1.addEventListener("touchcancel", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchcacel"
    })

    // タイムスタンプ取得
    function getTimeStamp(){
        const date = new Date()
        return ('0' + date.getHours()).slice(-2)
            + ':' + ('0' + date.getMinutes()).slice(-2)
            + ':' + ('0' + date.getSeconds()).slice(-2)
            + ':' + ('0' + date.getMilliseconds()).slice(-3)
    }
</script>

あれ? touch area の外に指を移動させたり、touch areaの外で指を離したりしてもイベントが発生するみたいだけど・・・?

それは私もハマったポイントよ。

例えば、touch areaに対して“touchend”のイベントリスナーを追加した場合、「touch area上でタッチを開始した指をスクリーンから離した時」にイベントが発火するわ。

「touch areaから指が離れた時」という条件ではない事に注意してね!“touchmove”も同じ考え方よ。

タッチの情報を取得する

先に説明したとおり、タッチを開始したり、指を動かしたり離したりすると、TouchEventが発生します。

TouchListとTouchオブジェクト

TouchEventオブジェクトは、3種のTouchListをもっており、その中に、タッチの情報(タッチした座標など)をもつTouchオブジェクトがあります。

下図は、この説明を図示したものです。
*指3本でタッチした後、さらにもう一本の指でタッチした時のイメージ

ユーザーのタッチ操作のイメージ
TouchEventの中身イメージ

タッチしてる指の情報が3種類のタッチリストで確認できるんだね~

3種のTouchList

TouchEventは、下記3種のTouchListをもっています。
リストごとに、含まれるTouchオブジェクト(≒指の情報)が異なりますので、用途によって使い分けが必要です。

touchesすべてのTouchオブジェクトを格納

*さっきの例では、合計4本の指でタッチしているので4つ
changedTouches変更されたTouchオブジェクトを格納

*さっきの例では、追加で③のタッチを行ったので、③の情報
targetTouchesイベントのターゲットと同じ要素でタッチを始めた
Touchオブジェクトを格納

*さっきの例では、③のターゲットである#blue-area要素でタッチが始まった3つ(⓪,①,③)

・・・で、どのリストを使えばいいの・・・?

う~ん、大体の場合はchangedTouchesを使えばいいんじゃないかな。

特に、指を離した時に、離した指の情報を取得できるのはchangedTouchesだけよ。

Touchオブジェクト

各タッチの情報は、Touchオブジェクトから取得することができます。

Touchオブジェクトは、触った指ごとに発生しますので、もし4本の指でタッチしたら4つのTouchオブジェクトが発生します。

Touchオブジェクトから取得できる主な情報は下表のとおりです。

identifier各タッチに付与される番号。
指のIDのようなもので、指を離すまではidentifierは変わりません
screenX端末のスクリーンの左端からの距離(px)
screenY端末のスクリーンの上端からの距離(px)
clientXブラウザのビューポートの左端からの距離(px)
clientYブラウザのビューポートの上端からの距離(px)
pageXドキュメントの上端からの距離(px)
pageYドキュメントの上端からの距離(px)
targetその指をタッチ開始した位置にあるElement
*指を移動しても、targetはタッチ開始時の位置のElementのまま
Touchオブジェクトの主なプロパティ

いっぱいあるけど、つまりは、指のID と 座標の情報 って感じだね

page、screen、clientの値の違いは、下の図を見ればわかるわよ~

それぞれの座標の意味

(参考として、HTML要素の座標についても右側に書いてみました。タッチした座標HTML要素の座標を比較することが、よくあると思うので・・・)

TouchList・Touchオブジェクトを理解するためのサンプル

こちらもお試し用のサンプルを作ってみました。
3つのTouchListの違いや、Touchオブジェクトの中身が理解できると思います。

【JavaScript】初心者でもわかるタッチイベント(touch event)

この記事では、スマートフォンやタブレット等によるタッチ操作をJavaScriptで取り扱うことができるtouchイベントについて、できるだけ簡単に解説します。

Web上に丁寧な記事はいくつもあったんだけど、正直、初心者プログラマーの僕には難しかった・・・。

執筆者も初心者で最近悩んだばかりだから、初心者の気持ちになった記事にできているかも・・・??

(簡単にするために、ちょっと大雑把な説明になります)

タッチイベントの種類

ユーザーが、画面をタッチで操作すると、操作の内容によって、以下のようなイベントが発生します。

イベント発生するタイミング
touchstartタッチ面に指が触れた時
touchendタッチしていた指を離した時
touchmoveタッチしながら指を移動させた時
touchcancel何らかの理由でタッチが取り消された時

まずは、下記のサンプルで、タッチイベント発生のイメージをつかんでください。

*touch areaに指を触れたり、離したり、動かしたりすると、発生したイベントと時刻がdisplay areaに表示されます。

touch area

display area

このデモのソースコードは下記のとおりです。

<div id="container1">
    <p>touch area</p>
    <div id="touch-area1"></div>
    <p>display area</p>
    <div id="display-area1"></div>
</div>
<script>
    const displayArea1 = document.getElementById("display-area1")
    const touchArea1 = document.getElementById("touch-area1")

    // touchstartイベント
    touchArea1.addEventListener("touchstart", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchstart"
    })

    // touchendイベント
    touchArea1.addEventListener("touchend", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchend"
    })

    // touchmoveイベント
    touchArea1.addEventListener("touchmove", () => {
        event.preventDefault();  // 画面スクロールを防止
        displayArea1.innerHTML = getTimeStamp() + " touchmove"
    })

    // touchcancelイベント
    touchArea1.addEventListener("touchcancel", () => {
        displayArea1.innerHTML = getTimeStamp() + " touchcacel"
    })

    // タイムスタンプ取得
    function getTimeStamp(){
        const date = new Date()
        return ('0' + date.getHours()).slice(-2)
            + ':' + ('0' + date.getMinutes()).slice(-2)
            + ':' + ('0' + date.getSeconds()).slice(-2)
            + ':' + ('0' + date.getMilliseconds()).slice(-3)
    }
</script>

あれ? touch area の外に指を移動させたり、touch areaの外で指を離したりしてもイベントが発生するみたいだけど・・・?

それは私もハマったポイントよ。

例えば、touch areaに対して“touchend”のイベントリスナーを追加した場合、「touch area上でタッチを開始した指をスクリーンから離した時」にイベントが発火するわ。

「touch areaから指が離れた時」という条件ではない事に注意してね!“touchmove”も同じ考え方よ。

タッチの情報を取得する

先に説明したとおり、タッチを開始したり、指を動かしたり離したりすると、TouchEventが発生します。

TouchListとTouchオブジェクト

TouchEventオブジェクトは、3種のTouchListをもっており、その中に、タッチの情報(タッチした座標など)をもつTouchオブジェクトがあります。

下図は、この説明を図示したものです。
*指3本でタッチした後、さらにもう一本の指でタッチした時のイメージ

ユーザーのタッチ操作のイメージ
TouchEventの中身イメージ

タッチしてる指の情報が3種類のタッチリストで確認できるんだね~

3種のTouchList

TouchEventは、下記3種のTouchListをもっています。
リストごとに、含まれるTouchオブジェクト(≒指の情報)が異なりますので、用途によって使い分けが必要です。

touchesすべてのTouchオブジェクトを格納

*さっきの例では、合計4本の指でタッチしているので4つ
changedTouches変更されたTouchオブジェクトを格納

*さっきの例では、追加で③のタッチを行ったので、③の情報
targetTouchesイベントのターゲットと同じ要素でタッチを始めた
Touchオブジェクトを格納

*さっきの例では、③のターゲットである#blue-area要素でタッチが始まった3つ(⓪,①,③)

・・・で、どのリストを使えばいいの・・・?

う~ん、大体の場合はchangedTouchesを使えばいいんじゃないかな。

特に、指を離した時に、離した指の情報を取得できるのはchangedTouchesだけよ。

Touchオブジェクト

各タッチの情報は、Touchオブジェクトから取得することができます。

Touchオブジェクトは、触った指ごとに発生しますので、もし4本の指でタッチしたら4つのTouchオブジェクトが発生します。

Touchオブジェクトから取得できる主な情報は下表のとおりです。

identifier各タッチに付与される番号。
指のIDのようなもので、指を離すまではidentifierは変わりません
screenX端末のスクリーンの左端からの距離(px)
screenY端末のスクリーンの上端からの距離(px)
clientXブラウザのビューポートの左端からの距離(px)
clientYブラウザのビューポートの上端からの距離(px)
pageXドキュメントの上端からの距離(px)
pageYドキュメントの上端からの距離(px)
targetその指をタッチ開始した位置にあるElement
*指を移動しても、targetはタッチ開始時の位置のElementのまま
Touchオブジェクトの主なプロパティ

いっぱいあるけど、つまりは、指のID と 座標の情報 って感じだね

page、screen、clientの値の違いは、下の図を見ればわかるわよ~

それぞれの座標の意味

(参考として、HTML要素の座標についても右側に書いてみました。タッチした座標HTML要素の座標を比較することが、よくあると思うので・・・)

TouchList・Touchオブジェクトを理解するためのサンプル

こちらもお試し用のサンプルを作ってみました。
3つのTouchListの違いや、Touchオブジェクトの中身が理解できると思います。

touch area

blue
red
touches
changedTouches
targetTouches

このサンプルのソースコードは以下のとおりです。

<div id="container2">
    <p>touch area</p>
    <div id="touch-area2">
        <div id="blue-area">blue</div>
        <div id="red-area">red</div>
    </div>
    <div>
        <span>touches</span>
        <button onclick="pushBtn('display-touches')">表示・非表示 切替</button>
        <div id="display-touches"></div>
    </div>
    <div>
        <span>changedTouches</span>
        <button onclick="pushBtn('display-changed-touches')">表示・非表示 切替</button>
        <div id="display-changed-touches"></div>
    </div>
    <div>
        <span>targetTouches</span>
        <button onclick="pushBtn('display-target-touches')">表示・非表示 切替</button>
        <div id="display-target-touches"></div>
    </div>
</div>
<script>
    // 要素の取得
    const touchArea2 = document.getElementById("touch-area2")
    const displayTouches = document.getElementById("display-touches")
    const displayChangedTouches = document.getElementById("display-changed-touches")
    const displayTargetTouches = document.getElementById("display-target-touches")

    // 各タッチイベントのイベントリスナー登録
    touchArea2.addEventListener("touchstart", function(){ updateDisplay(event) } )
    touchArea2.addEventListener("touchend", function(){ updateDisplay(event) } )
    touchArea2.addEventListener("touchmove",function(){ 
        event.preventDefault()  // 画面スクロールを防止
        updateDisplay(event) 
    } )
    touchArea2.addEventListener("touchcancel",function(){ updateDisplay(event) } )

    // タッチの情報を画面に表示する
    function updateDisplay(event){
        displayTouches.innerHTML = getTouchInfo(event.touches)
        displayChangedTouches.innerHTML = getTouchInfo(event.changedTouches)
        displayTargetTouches.innerHTML = getTouchInfo(event.targetTouches)
    }

    // 与えられたタッチリストからタッチ情報を取得
    function getTouchInfo(touchList){
        let displayStr = ""
        for ( const touch of touchList ){
            displayStr += `
            identifier: ${touch.identifier}<br>
            screenX:    ${touch.screenX}<br>
            screenY:    ${touch.screenY}<br>
            clientX:    ${touch.clientX}<br>
            clientY:    ${touch.clientY}<br>
            pageX:      ${touch.pageX}<br>
            pageY:      ${touch.pageY}<br>
            target:     ${touch.target.id}<br>
            --------------------------------------<br>`
        }
        return displayStr
    }

    // 表示・非表示ボタン
    function pushBtn(targetId){
        document.getElementById(targetId).classList.toggle('hide')
    }
</script>

勘違いしやすい(?)ポイント

他の人はどうかわかりませんが、私が勘違いしたポイントをメモしておきます。

1.touchmoveとtouchendの発火

:イベントリスナーを追加した要素の上で指を動かす・指を離すと発火
:イベントリスナーを追加した要素の上でタッチを開始した指を動かす・離すと発火

2.TouchListに入っているtouchオブジェクト

:イベントリスナーを追加した要素の上でタッチした指の情報
:スクリーンにタッチした指の情報

先ほどのサンプルで、タッチエリア以外の部分をタッチしながら、他の指でタッチエリアを触ると、この意味がわかると思います。

3.Touchオブジェクトのtarget

:現在触れているHTML要素
:そのタッチを開始した時に触れたHTML要素

参考

touchイベントを初めて学んで作った成果物です

MDNのTouchの解説ページ

TouchEvent - Web API | MDN
TouchEvent インターフェイスは、タッチ感応面への接触状態が変化したときに発生する UIEvent を表します。この面は、例えばタッチ画面やトラックパッドです。このイベントは画面との 1 か所以上の接触を表すことが可能であり、また接触個所の移動、増加、減少などに対応することができます。
TouchList - Web API | MDN
TouchList インターフェイスは、タッチ面上の接触点のリストを表します。例えば、ユーザーがタッチ面(画面やトラックパッドなど)を 3 本指で操作している場合、対応する TouchList オブジェクトは 1 本の指あたり 1 つの Touch オブジェクトを持ち、全部で 3 項目になります。
Touch - Web API | MDN
Touch インターフェイスは、タッチ感応面へのひとつの接触点を表します。接触点とは一般的に指やスタイラスと、タッチ画面やトラックパッドのような機器が触れた位置です。

コメント