クイック スタート: ポインター (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

JavaScript を使ったアプリでは、タッチ、マウス、ペン/スタイラスの対話式操作は、ポインター入力として受信、処理、管理されます。

Windows 8.1 の変更点: Windows 8.1 では、ポインター入力 API に対するさまざまな変更や改良が行われています。詳しくは、「Windows 8.1 の API の変更点」をご覧ください。

JavaScript を使ってアプリを開発するのが初めての場合: 以下のトピックに目を通して、ここで説明されているテクノロジをよく理解できるようにしてください。

JavaScript を使った初めての Windows ストア アプリの作成

JavaScript を使った Windows ストア アプリのためのロードマップ

イベントについては、「クイック スタート: HTML コントロールの追加とイベントの処理」をご覧ください。

アプリの機能の概要:

この機能について詳しくは、「アプリの機能の概要」シリーズをご覧ください。

ユーザー操作の概要 (HTML)

ユーザー操作のカスタマイズの概要 (HTML)

ユーザー エクスペリエンス ガイドライン:

プラットフォーム コントロール ライブラリ (HTMLXAML) は、標準的な対話式操作、アニメーション化された物理的効果、視覚的フィードバックなど、Windows の完全なユーザー操作エクスペリエンスを提供しています。 操作のサポートをカスタマイズする必要がない場合は、これらのビルトイン コントロールを使います。

プラットフォーム コントロールでは十分に対応できない場合は、以下のユーザー操作ガイドラインに従うと、どの入力モードでも一貫性のある、魅力的でイマーシブな対話式操作エクスペリエンスを実現できます。これらのガイドラインは、主にタッチ入力を対象として説明していますが、タッチパッド、マウス、キーボード、スタイラスでの入力にも当てはまります。

サンプル: アプリのサンプルで、この機能の動作を実際に確かめることができます。

ユーザー操作のカスタマイズの概要のサンプルに関するページ

HTML のスクロール、パン、ズームのサンプルに関するページ

入力: DOM ポインター イベント処理のサンプルに関するページ

入力: インスタンス化できるジェスチャのサンプルに関するページ

入力: インクのサンプルに関するページ

入力: 操作とジェスチャ (JavaScript) のサンプルに関するページ

入力: 簡略化されたインクのサンプル

目標: ポインター入力をリッスンして処理する方法について理解する。

必要条件

JavaScript 用 Windows ライブラリのテンプレートが使われた JavaScript を使った基本的なアプリの作成経験が必要です。

このチュートリアルを行うには、次の作業を行う必要があります。

完了までの時間: 30 分.

手順

ポインター入力とは

マウス、ペン/スタイラス、タッチ入力を抽象ポインター入力として統合することで、使われている入力デバイスの種類とは関係なくアプリでユーザー操作を処理できます。

ポインター オブジェクトは、入力デバイス (マウス、ペン/スタイラス、1 本の指、複数の指など) からの、個別の 1 回の入力の "接触" (PointerPoint) を表します。システムは、接触が最初に検出されるとポインターを作り、ポインターが検出範囲から離れる (外れる) と、または取り消されると、ポインターを破棄します。複数デバイスまたはマルチタッチの入力の場合には、各接触は固有のポインターとして扱われます。

さまざまなデバイスから直接入力データを取得するポインター ベースの入力 API の広範なセットがあります。ポインター イベントを処理することで、場所やデバイスの種類などの一般的な情報と、圧力や接触形状などの拡張情報を取得できます。通常、アプリは異なる入力モードには異なる方法で応える必要があるため、ユーザーが押したマウス ボタンは何か、ユーザーはペンの消しゴム ボタンを使っているか、といったデバイスの特定のプロパティも使うことができます。たとえば、タッチはパンやスクロールなどの対話式操作をサポートするためにフィルター処理できますが、一方でマウスとペン/スタイラスは通常、手書きや線画のような精密なタスクにより適しています。アプリで入力デバイスとその機能を区別する必要がある場合は、「クイック スタート: 入力デバイスの識別」をご覧ください。

独自の対話式操作サポートを実装する場合は、ユーザーはアプリの UI 要素を直接操作できる直感的なエクスペリエンスを期待しているということを心に留めておいてください。 フレームワーク コントロールでのカスタムの対話式操作をモデル化し、一貫性と見つけやすさを維持することをお勧めします。はっきりとした明確に定義されている要件があり、基本的な対話式操作ではシナリオがサポートされない場合のみ、カスタムの対話式操作を作ってください。

UI を作る

この例では、ポインター入力のターゲット オブジェクトとして四角形 (target) を使います。ポインターの状態が変わると、ターゲットの色が変わります。

ポインターの隣にあり、ポインターの動きに付いていく浮動テキスト ブロックに、各ポインターの詳細が表示されます。画面の右端には、個別のポインター イベントが報告されます。次のスクリーン ショットは、この例の UI を示しています。

サンプル アプリの UI のスクリーン ショット。

この例の HTML を次に示します。

  Windows ストア アプリ

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>PointerInput_Universal.Windows</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- PointerInput_Universal.Windows references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body class="windows">
    <div id="grid">
        <div id="targetContainer">
            <div id="target"></div>
        </div>
        <div id="bottom">
        </div>
        <div id="eventLog"></div>
    </div>
</body>
</html>

  Windows Phone ストア アプリ

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>PointerInput_Universal.WindowsPhone</title>

    <!-- WinJS references -->
    <!-- At runtime, ui-themed.css resolves to ui-themed.light.css or ui-themed.dark.css 
    based on the user’s theme setting. This is part of the MRT resource loading functionality. -->
    <link href="/css/ui-themed.css" rel="stylesheet" />
    <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
    <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>

    <!-- PointerInput_Universal.Phone references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body class="phone">
    <div id="grid">
        <div id="targetContainer">
            <div id="target"></div>
        </div>
        <div id="bottom">
        </div>
        <div id="eventLog"></div>
    </div>
</body>
</html>

この例のカスケード スタイル シート (CSS) を次に示します。

  パンまたはズームの操作中はポインター イベントが発生しません。領域のパンとズームは、CSS プロパティ msTouchActionoverflow-ms-content-zooming を使って無効にできます。

 

body {
    overflow: hidden;
    position: relative;
}

#grid {
    display: -ms-grid;
    height: 100vh; /* 100% of viewport height */
    -ms-grid-columns: 4fr 1fr; /* 2 columns */
    -ms-grid-rows: 1fr 320px 1fr;  /* 3 rows */
    /*touch-action: none;*/ /* Disable panning and zooming */
}
#targetContainer {
    border:solid;
    border-width:thin;
    border-color: red;
    -ms-grid-row: 2;
    -ms-grid-column: 1;
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
    /*touch-action: none; /* Disable panning and zooming */*/
}
#eventLog {
    -ms-grid-row: 1;
    -ms-grid-column: 2; 
    -ms-grid-row-span: 3;
    padding-right: 10px;
    background-color: black;
    color: white;
}
.phone #target {
    width: 200px;
    height: 300px;
    border: none;
    padding: 0px;
    margin: 0px;
    -ms-transform-origin: 0% 0%;
    /*touch-action: none; /* Disable panning and zooming */*/
}
.windows #target {
    width: 400px;
    height: 200px;
    border: none;
    padding: 0px;
    margin: 0px;
    -ms-transform-origin: 0% 0%;
    touch-action: none; /* Disable panning and zooming */
}

ポインター イベントをリッスンする

ほとんどの場合は、選んだ言語フレームワークのポインター イベント ハンドラーのイベント引数を介してポインター情報を取得することをお勧めします。

アプリに必要なポインターの詳細をイベント引数が公開していない場合は、getCurrentPointgetIntermediatePoints メソッドか、currentPointintermediatePoints プロパティを通じて、イベント引数の拡張ポインター データにアクセスできます。ポインター データのコンテキストを指定できるので、getCurrentPointgetIntermediatePoints メソッドを使うことをお勧めします。

次のスクリーン ショットは、ターゲット領域と、この例のマウス ポインターの詳細を示しています。

ポインターのターゲット領域のスクリーンショット。

ここでは、ターゲット領域の画面上の場所とイベント リスナーを設定します。

まず、グローバル変数を宣言し、ターゲットとポインターの詳細領域を初期化し、イベント ログ ツールを識別します。

// For this example, we track simultaneous contacts in case the 
// number of contacts has reached the maximum supported by the device.
// Depending on the device, additional contacts might be ignored 
// (PointerPressed not fired). 
var numActiveContacts = 0;

// The input target.
var target;

// Target background colors corresponding to various pointer states.
var pointerColor = {
    hover: "rgb(255, 255, 102)",
    down: "rgb(0, 255, 0)",
    up: "rgb(255, 0, 0)",
    cancel: "rgb(0,0,0)",
    out: "rgb(127,127,127)",
    over: "rgb(0,0,255)"
};

// The event log (updated on each event).
var eventLog;

function initialize() {
    /// <summary>Set up the app.</summary>
    eventLog = document.getElementById("eventLog");
    target = document.getElementById("target");
    setTarget();
}

次に、ターゲット オブジェクトを設定し、ターゲットのさまざまなポインター イベント リスナーを宣言します。

function setTarget() {
    /// <summary>Set up the target and interaction event handlers.</summary>

    // Initial color of target.
    target.style.backgroundColor = pointerColor.out;

    // Expando dictionary property to track active contacts. 
    // An entry is added during pointer down/hover/over events 
    // and removed during pointer up/cancel/out/lostpointercapture events.
    target.pointers = [];

    // Declare pointer event handlers.
    target.addEventListener("pointerdown", onPointerDown, true);
    target.addEventListener("pointerover", onPointerOver, true);
    target.addEventListener("pointerup", onPointerUp, true);
    target.addEventListener("pointerout", onPointerOut, true);
    target.addEventListener("pointercancel", onPointerCancel, true);
    target.addEventListener("lostpointercapture", onLostPointerCapture, true);
    target.addEventListener("pointermove", onPointerMove, true);
    target.addEventListener("wheel", onMouseWheel, false);
}

最後に、ポインターの詳細領域を設定します。

function createInfoPop(e) {
    /// <summary>
    /// Create and insert DIV into the DOM for displaying pointer details.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>
    var infoPop = document.createElement("div");
    infoPop.setAttribute("id", "infoPop" + e.pointerId);

    // Set screen position of DIV.
    var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20);
    infoPop.style.msTransform = transform;
    target.appendChild(infoPop);

    infoPop.innerText = queryPointer(e);
}

function updateInfoPop(e) {
    /// <summary>
    /// Update pointer details in UI.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>
    var infoPop = document.getElementById("infoPop" + e.pointerId);
    if (infoPop === null)
        return;

    // Set screen position of DIV.
    var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20);
    infoPop.style.msTransform = transform;
    infoPop.innerText = queryPointer(e);
}

ポインター イベントを処理する

次に、UI フィードバックを使って基本的なポインター イベント ハンドラーを示します。

  • このハンドラーは、ポインター接触 (ダウン、押す) イベントを管理します。イベント ログにイベントを追加し、関心のあるポインターを追跡するために使われるポインター配列にポインターを追加し、ポインターの詳細を表示します。

      pointerdown イベントと pointerup イベントは常に対で発生するわけではありません。アプリでは、ポインター ダウン アクションを終了させる可能性のあるすべてのイベント (pointeruppointeroutpointercancellostpointercapture など) をリッスンして処理する必要があります。

     

    function onPointerDown(e) {
        /// <summary>
        /// Occurs for mouse when at least one mouse button is pressed or 
        /// for touch and pen when there is physical contact with the digitizer.
        /// For input devices that do not support hover, the pointerover event is 
        /// fired immediately before the pointerdown event.  
        /// Here, we  filter pointer input based on the first pointer type detected. 
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // pointerdown and pointerup events do not always occur in pairs. 
        // Listen for and handle any event that might conclude a pointer down action 
        // (such as pointerup, pointerout, pointercancel, and lostpointercapture).
        //
        // For this example, we track the number of contacts in case the 
        // number of contacts has reached the maximum supported by the device.
        // Depending on the device, additional contacts might be ignored 
        // (PointerPressed not fired). 
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Check if the number of supported contacts is exceeded.
        var touchCapabilities = new Windows.Devices.Input.TouchCapabilities();
        if ((touchCapabilities.touchPresent != 0) & (numActiveContacts > touchCapabilities.contacts)) {
            return;
        }
    
        // Update event details and target UI.
        eventLog.innerText += "\nDown: " + e.pointerId;
        target.style.backgroundColor = pointerColor.down;
    
        // Check if pointer already exists (if hover/over occurred prior to down).
        for (var i in target.pointers) {
            if (target.pointers[i].id = e.pointerId) {
                return;
            }
        }
    
        // Push new pointer Id onto expando target pointers array.
        target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
        // Ensure that the element continues to receive PointerEvents 
        // even if the contact moves off the element. 
        // Capturing the current pointer can improve usability by reducing 
        // the touch precision required when interacting with an element.
        // Note: Only the assigned pointer is affected. 
        target.setPointerCapture(e.pointerId);
    
        // Display pointer details.
        createInfoPop(e);
    }
    
  • このハンドラーは、ターゲット領域との接触や領域内の移動を表すポインター進入 (オーバー) イベントを管理します。イベント ログにイベントを追加し、ポインター配列にポインターを追加して、ポインターの詳細を表示します。

    接触はしていないもののターゲット (通常、ペン/スタイラス デバイス) の領域内にあるポインターのホバー状態の処理については、pointermove イベントの説明をご覧ください。

    function onPointerOver(e) {
        /// <summary>
        /// Occurs when a pointer is detected within the hit test boundaries 
        /// of an element.
        /// Also occurs prior to a pointerdown event for devices that do not 
        /// support hover.  
        /// This event type is similar to pointerenter, but bubbles. 
        /// See the pointermove event for handling the hover state of a pointer 
        /// that is not in contact but is within the boundary of the target 
        /// (typically a pen/stylus device). 
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details and target UI.
        eventLog.innerText += "\nOver: " + e.pointerId;
    
        if (target.pointers.length === 0) {
            // Change background color of target when pointer contact detected.
            if (e.getCurrentPoint(e.currentTarget).isInContact) {
                // Pointer down occured outside target.
                target.style.backgroundColor = pointerColor.down;
            } else {
                // Pointer down occured inside target.
                target.style.backgroundColor = pointerColor.over;
            }
        }
    
        // Check if pointer already exists.
        for (var i in target.pointers) {
            if (target.pointers[i].id = e.pointerId) {
                return;
            }
        }
    
        // Push new pointer Id onto expando target pointers array.
        target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
        // Ensure that the element continues to receive PointerEvents 
        // even if the contact moves off the element. 
        // Capturing the current pointer can improve usability by reducing 
        // the touch precision required when interacting with an element.
        // Note: Only the assigned pointer is affected. 
        target.setPointerCapture(e.pointerId);
    
        // Display pointer details.
        createInfoPop(e);
    }
    
  • このハンドラーは、ポインター移動イベントを管理します。イベント ログにイベントを追加し、ポインターの詳細を更新 (ホバー イベントの場合は、ポインターの配列にも追加) します。

    MSPointerHover は、Windows 8.1 では推奨されなくなりました。pointermoveIsInContact ポインター プロパティを使ってホバー状態を調べてください。

       複数のマウス ボタンの同時のクリックも、このハンドラーで処理されます。マウス入力は、最初に検出されたときに割り当てられた 単一ポインターに関連付けられます。操作中に追加のマウス ボタン (左、 ホイール、または右) をクリックすると、ポインター押下イベントを通じて、これらのボタンとポインターとの間に 副次的な関連付けが行われます。 ポインター解放イベントは、操作に関連付けられている最後のマウス ボタン (最初のボタンとは限りません) が 離されたときにだけ発生します。 この排他的な関連付けのために、他のマウス ボタンをクリックした場合は、 ポインター移動イベントによってルーティングされます。

     

     function onPointerMove(e) {
         /// <summary>
         /// Occurs when a pointer moves within the hit test boundaries 
         /// of an element.
         /// </summary>
         /// <param name="e" type="Event">The event argument.</param>
    
         // NOTE: Multiple, simultaneous mouse button inputs are processed here.
         // Mouse input is associated with a single pointer assigned when 
         // mouse input is first detected. 
         // Clicking additional mouse buttons (left, wheel, or right) during 
         // the interaction creates secondary associations between those buttons 
         // and the pointer through the pointer pressed event. 
         // The pointer released event is fired only when the last mouse button 
         // associated with the interaction (not necessarily the initial button) 
         // is released. 
         // Because of this exclusive association, other mouse button clicks are 
         // routed through the pointer move event.  
    
         // Prevent the next handler in the hierarchy from receiving the event.
         e.cancelBubble = true;
    
         if (e.pointerType == "mouse") {
             // Mouse button states are extended PointerPoint properties.
             var pt = e.getCurrentPoint(e.currentTarget);
             var ptProperties = pt.properties;
             if (ptProperties.isLeftButtonPressed) {
                 eventLog.innerText += "\nLeft button: " + e.pointerId;
             }
             if (ptProperties.isMiddleButtonPressed) {
                 eventLog.innerText += "\nWheel button: " + e.pointerId;
             }
             if (ptProperties.isRightButtonPressed) {
                 eventLog.innerText += "\nRight button: " + e.pointerId;
             }
         }
         // Handle hover state of a pointer that is not in contact but is within 
         // the boundary of the target (typically a pen/stylus device). 
         if (e.pointerType == "pen") {
             var pt = e.getCurrentPoint(e.currentTarget);
             if (pt.isInContact == false) {
                 // Update event details and target UI.
                 target.style.backgroundColor = pointerColor.hover;
                 eventLog.innerText = "\nHover: " + e.pointerId;
    
                 // Check if pointer already exists.
                 for (var i in target.pointers) {
                     if (target.pointers[i].id = e.pointerId) {
                         updateInfoPop(e);
                         return;
                     }
                 }
    
                 target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
                 // Ensure that the element continues to receive PointerEvents 
                 // even if the contact moves off the element. 
                 // Capturing the current pointer can improve usability by reducing 
                 // the touch precision required when interacting with an element.
                 // Note: Only the assigned pointer is affected. 
                 target.setPointerCapture(e.pointerId);
             }
         }
    
         // Display pointer details.
         updateInfoPop(e);
     }
    
  • このハンドラーは、マウス ホイール イベント (回転) を管理します。イベント ログにイベントを追加し、ポインター配列にポインターを追加して (必要な場合)、ポインターの詳細を表示します。

    function onMouseWheel(e) {
        /// <summary>  
        /// Occurs when the mouse wheel is rotated. 
        /// </summary> 
        /// <param name="e" type="Event">The event argument.</param>
        // Check if a mouse pointer already exists.
        for (var i in target.pointers) {
            // Ensure existing pointer type registered with pointerover is mouse. 
            if (target.pointers[i].type === "mouse") {
                e.pointerId = target.pointers[i].id;
                break;
            }
        }
        eventLog.innerText += "\nMouse wheel: " + e.pointerId;
        // For this example, we fire a corresponding pointer down event.
        onPointerDown(e);
    }
    
  • このハンドラーは、ポインター退出 (アップ) イベントを管理します。イベント ログにイベントを追加し、ポインター配列からポインターを削除して、ポインターの詳細を更新します。

    function onPointerUp(e) {
        /// <summary>
        /// Occurs for mouse at transition from at least one button pressed 
        /// to no buttons pressed.
        /// Occurs for touch and pen when contact is removed from the digitizer. 
        /// For input devices that do not support hover, the pointerout event 
        /// is fired immediately after the pointerup event.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nUp: " + e.pointerId;
    
        // If event source is mouse pointer and the pointer is still 
        // over the target, retain pointer and pointer details.
        // Return without removing pointer from pointers dictionary.
        // For this example, we assume a maximum of one mouse pointer.
        if ((e.pointerType === "mouse") &
            (document.elementFromPoint(e.x, e.y) === target)) {
            target.style.backgroundColor = pointerColor.up;
            return;
        }
    
        // Ensure capture is released on a pointer up event.
        target.releasePointerCapture(e.pointerId);
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
            }
        }
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.up;
        }
    }
    
  • このハンドラーは、ポインター退出 (アウト) イベントを管理します。イベント ログにイベントを追加し、ポインター配列からポインターを削除して、ポインターの詳細を更新します。

    function onPointerOut(e) {
        /// <summary>
        /// Occurs when a pointer (in contact or not) moves out of the 
        /// target hit test boundary, after a pointerup event for a device 
        /// that does not support hover, and after a pointercancel event. 
        /// This event type is similar to pointerleave, but bubbles.  
        /// Note: Pointer capture is maintained until pointer up event.
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nPointer out: " + e.pointerId;
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
    
                // Update target UI.
                if (target.pointers.length === 0) {
                    target.style.backgroundColor = pointerColor.out;
                }
            }
        }
    }
    
  • このハンドラーは、ポインター キャンセル イベントを管理します。イベント ログにイベントを追加し、ポインター配列からポインターを削除して、ポインターの詳細を更新します。

    function onPointerCancel(e) {
        /// <summary>
        /// Occurs when a pointer is removed.
        /// The app will not receive subsequent events for that pointer, including pointerup.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // A pointer can be canceled as a result of one of the following:
        //    - A touch contact is canceled when a pen is detected.
        //    - More than 100ms has passed since the device reported
        //      an active contact.
        //    - The desktop is locked or the user logged off. 
        //    - The number of simultaneous contacts exceeds the number 
        //      supported by the device.
        //    - The system has determined that a pointer is unlikely to 
        //      continue to produce events (for example, due to a hardware event).
        //    - After a pointerdown event, the pointer is subsequently used to 
        //      manipulate the page viewport (for example, panning or zooming).  
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nPointer canceled: " + e.pointerId;
    
        // Ensure capture is released on a pointer cancel event.
        target.releasePointerCapture(e.pointerId);
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.cancel;
        }
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
    
                // Update target UI.
                if (target.pointers.length === 0) {
                    target.style.backgroundColor = pointerColor.out;
                }
            }
        }
    }
    
  • このハンドラーは、ロスト ポインター キャプチャ イベントを管理します。イベント ログにイベントを追加し、ポインター配列からポインターを削除して、ポインターの詳細を更新します。

      lostpointercapturepointerup の代わりに発生することがあります。ユーザー操作のために、または別のポインターがプログラムでキャプチャされたり、現在のポインター キャプチャが意図的に解除されたりしたために、ポインター キャプチャが失われることがあります。

     

    function onLostPointerCapture(e) {
        /// <summary>
        /// Occurs after pointer capture is released for the pointer.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // lostpointercapture can fire instead of pointerup. 
    
        // Pointer capture can be lost as a result of one of the following:
        //    - User interactions
        //    - Programmatic caputre of another pointer
        //    - Captured pointer was deliberately released
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nLost pointer capture: " + e.pointerId;
    
        // We need the device type to handle lost pointer capture from mouse input.
        // Use the getCurrentPoint method over currentPoint property to ensure
        // the coordinate space is in relation to the target element.
        // Note: getCurrentPoint and currentPoint are only available in the 
        // local compartment, they are not available in the web compartment.
        var ptTarget = e.getCurrentPoint(e.currentTarget);
        var ptContainer = e.getCurrentPoint(document.getElementsByTagName("body")[0]);
    
        // If event source is mouse pointer and the pointer is still over 
        // the target, retain pointer and pointer details.
        // For this example, we assume only one mouse pointer.
        if ((ptTarget.pointerDevice.pointerDeviceType === Windows.Devices.Input.PointerDeviceType.mouse) &
            (document.elementFromPoint(ptContainer.position.x, ptContainer.position.y) === target)) {
            target.setPointerCapture(e.pointerId);
            return;
        }
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
            }
        }
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.cancel;
        }
    }
    

ポインターのプロパティを取得する

アプリに対して選んだ言語フレームワークで、ポインター プロパティの取得方法が示されます。ポインター イベント オブジェクトでは、多くのプロパティが直接公開されています。前に説明したように、追加のポインター情報は、イベント引数の getCurrentPointgetIntermediatePoints メソッドか、currentPointintermediatePoints プロパティを通じて取得できます。ポインター データのコンテキストを指定できるので、getCurrentPointgetIntermediatePoints メソッドを使うことをお勧めします。

ここでは、イベント オブジェクト自体のさまざまなポインター プロパティと、PointerPoint および PointerPointProperties オブジェクトを通じてだけ利用できる拡張プロパティを照会しています。

function queryPointer(e) {
    /// <summary>
    /// Get extended pointer data.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>

    // We get the extended pointer info through the getCurrentPoint method
    // of the event argument. (We recommend using getCurrentPoint 
    // to ensure the coordinate space is in relation to the target.)
    // Note: getCurrentPoint and currentPoint are only available in the 
    // local compartment, they are not available in the web compartment.

    var pt = e.getCurrentPoint(e.currentTarget);
    var ptTargetProperties = pt.properties;

    var details = "Pointer Id: " + e.pointerId;
    switch (e.pointerType) {
        case "mouse":
            details += "\nPointer type: mouse";
            details += "\nLeft button: " + ptTargetProperties.isLeftButtonPressed;
            details += "\nRight button: " + ptTargetProperties.isRightButtonPressed;
            details += "\nWheel button: " + ptTargetProperties.isMiddleButtonPressed;
            details += "\nX1 button: " + ptTargetProperties.isXButton1Pressed;
            details += "\nX2 button: " + ptTargetProperties.isXButton2Pressed;
            break;
        case "pen":
            details += "\nPointer type: pen";
            if (pt.isInContact) {
                details += "\nPressure: " + ptTargetProperties.pressure;
                details += "\nrotation: " + ptTargetProperties.rotation;
                details += "\nTilt X: " + ptTargetProperties.xtilt;
                details += "\nTilt Y: " + ptTargetProperties.ytilt;
                details += "\nBarrel button pressed: " + ptTargetProperties.isBarrelButtonPressed;
            }
            break;
        case "touch":
            details += "\nPointer type: touch";
            details += "\nPressure: " + ptTargetProperties.pressure;
            details += "\nrotation: " + ptTargetProperties.rotation;
            details += "\nTilt X: " + ptTargetProperties.xtilt;
            details += "\nTilt Y: " + ptTargetProperties.ytilt;
            break;
        default:
            details += "\nPointer type: " + "n/a";
            break;
    }
    details += "\nPointer location (target): " + e.offsetX + ", " + e.offsetY;
    details += "\nPointer location (screen): " + e.screenX + ", " + e.screenY;

    return details;
}

さらに複雑なサンプルへのリンクについては、このページの最後にある関連トピックをご覧ください。

完全な例

ポインターのコード一式」をご覧ください。

要約と次のステップ

このクイック スタートでは、JavaScript を使ったアプリでのポインター入力について説明しました。

ポインター イベントは、タップやスライドなどの単純な対話式操作と、セカンダリ マウス ボタン、マウス ホイール、ペン バレル ボタン、ペンの消しゴムからの入力を含むデバイス固有のその他の対話式操作の管理に便利です。

Windows 8 のタッチ言語で記述されているジェスチャなどのさらに複雑な対話式操作の処理については、「クイック スタート: DOM ジェスチャおよび操作」、「クイック スタート: 静的ジェスチャ」、「クイック スタート: 操作ジェスチャ」をご覧ください。

Windows 8 のタッチ言語について詳しくは、「タッチ操作の設計」をご覧ください。

関連トピック

開発者向け

ユーザー操作への応答

Windows ストア アプリの開発 (JavaScript と HTML)

クイック スタート: DOM ジェスチャおよび操作

クイック スタート: 静的ジェスチャ

クイック スタート: 操作ジェスチャ

デザイナー向け

タッチ操作の設計