次の方法で共有


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

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

Windows のタッチ言語」で記述されている操作ジェスチャ (スライド、スワイプ、回転、ピンチ、ストレッチなど) のユーザー エクスペリエンスをカスタマイズできます。そのためには、JavaScript を使ったアプリで Windows ランタイム ジェスチャ イベントを処理します。

ほとんどのアプリはジェスチャ (回転、ズーム、ドラッグなど) を処理し、生のポインター データはジェスチャ検出へ渡す場合を除いてほとんど使いません。このサンプルでは、操作ジェスチャの処理のサポートで、この生のポインター データを使います。そうすることでアプリの操作モデルを拡張し、「クイック スタート: ポインター」に記載されている基本的なポインター イベントをベースに構築することができます。

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

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

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

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

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

アプリの機能の概要:

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

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

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

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

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

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

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

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

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

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

目標: タッチ、マウス、ペン/スタイラスによる対話式操作からの入力と Windows ランタイム ジェスチャ イベントを使って操作ジェスチャをリッスンし、処理する方法について理解します。

必要条件

クイック スタート: ポインター」、「クイック スタート: DOM ジェスチャおよび操作」、「クイック スタート: 静的ジェスチャ」をご覧ください。

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

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

ジェスチャ イベントとは

ジェスチャは、入力デバイス上で、または入力デバイスによって実行される物理的な動作や動きです。これには、タッチ画面での 1 本または複数の指、ペン/スタイラス デジタイザー、マウスなどが含まれます。これらの自然な対話式操作は、システムとアプリの両方の要素に対する操作にマップされます。 詳しくは、「ジェスチャ、操作、対話的操作」をご覧ください。

次の表に、このクイック スタートで説明する操作ジェスチャについて定義します。タップや長押しなどの静的ジェスチャのサポートについては、「クイック スタート: 静的ジェスチャ」をご覧ください。

ジェスチャ説明
スライドスライド ジェスチャ

距離のしきい値を超えて移動する 1 か所以上の接触です。

パンが有効になっておらず、要素の境界内に最初に接触した場合、スライドすると要素が移動します。

パンが有効になっていて、要素の境界内に最初に接触し、スライドの方向がパンの軸に対して垂直の場合、スライドすると要素が移動します。それ以外の場合は、パンが開始されます。

  • 開始時の状態: 1 か所以上の接触が検出される。
  • 動作: 距離のしきい値を超えてドラッグまたはスライド。
  • 終了時の状態: 最後の接触が離される (終了する)。
スワイプスワイプ ジェスチャ

距離のしきい値以内で移動する 1 か所以上の接触 (短いスライド ジェスチャ) です。スワイプは速度や時間に基づくジェスチャではありません。

アプリでパンが有効になっておらず、要素の境界内に最初に接触した場合、スワイプすると要素が移動します。

アプリでパンが有効になっていて、要素の境界内に最初に接触し、スワイプの方向がパンの軸に対して垂直の場合、スワイプすると要素が選ばれます。それ以外の場合は、スワイプするとパンが開始されます。

  • 開始時の状態: 1 か所以上の接触が検出される。
  • 動作: 距離のしきい値を超えずにドラッグまたはスライド。
  • 終了時の状態: 最後の接触が離される (終了する)。
ピンチとストレッチピンチとストレッチのジェスチャ

拡大するときは近づけ、縮小するときは広げる 2 か所以上の接触です。

通常は、オブジェクトのサイズ変更、表示の拡大または縮小、セマンティック ズームに使います。

  • 開始時の状態: オブジェクトの境界の四角形内で 2 か所以上の接触が検出される。
  • 動作: 接触が近づく、または接触が広がるドラッグまたはスライド。
  • 終了時の状態: 2 か所より少ない接触が検出される。
回転回転ジェスチャ

2 本以上の指を別々の方向になぞると、オブジェクトが回転します。画面全体を回転させるには、デバイスを回転させます。

回転の中心 (つまり点) の周りを円を描くように移動する 2 か所以上の接触です。

通常はオブジェクトを回転させるために使います。

  • 開始時の状態: オブジェクトの境界の四角形内で 2 か所以上の接触が検出される。
  • 動作: 1 か所以上の接触を円を描くようにドラッグまたはスライド。
  • 終了時の状態: 2 か所より少ない接触が検出される。

これらのジェスチャと、Windows 8 のタッチ言語との関係について詳しくは、「タッチ操作の設計」をご覧ください。

 

重要  独自の対話式操作サポートを実装する場合は、ユーザーはアプリの UI 要素を直接操作できる直感的なエクスペリエンスを期待しているということを心に留めておいてください。 プラットフォーム コントロール ライブラリ (HTMLXAML) でのカスタムの対話式操作をモデル化し、一貫性と見つけやすさを維持することをお勧めします。これらのライブラリのコントロールでは、標準的な対話式操作、アニメーション化された物理的効果、視覚的フィードバック、アクセシビリティなど、完全なユーザー操作エクスペリエンスが提供されます。はっきりとした明確に定義されている要件があり、基本的な対話式操作ではシナリオがサポートされない場合のみ、カスタムの対話式操作を作ってください。

 

UI を作る

この例では、1 つの操作ジェスチャ、指を違う方向に動かすことによる回転を基本 UI 要素で有効にする方法を示しています。正方形 (target) は、ポインター入力と検出のターゲット オブジェクトとして機能します。このポインター データは、回転ジェスチャのデータを処理して、標準的な慣性動作を使った回転操作を作成する GestureRecognizer オブジェクトに渡されます。

このアプリには、次のユーザー操作機能があります。

  • 回転: オブジェクトを回転させます。ポインター接触が終了したときは、慣性を持ちます。この操作の動作は、「視覚的なフィードバックのガイドライン」と Windows のタッチ言語の推奨事項に従っています。これらの推奨事項では、回転ジェスチャは UI 要素の回転に限定されるべきだと述べられています。  この例は簡単な変更でドラッグとズームをサポートできます。これについては、このクイック スタートの後半で説明します。  

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

<html>
<head>
    <meta charset="utf-8" />
    <title>Manipulation Gestures</title>
    
    <!-- WinJS references -->
    <link rel="stylesheet" href="//Microsoft.WinJS.2.0/css/ui-light.css" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- BasicGesture references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/InputProcessor.js"></script>
    <script src="/js/ManipulationManager.js"></script>
    <script src="/js/default.js"></script>
</head>
<body>
    <div class="Container" id="Container">
        <div id="targetTitle">Manipulation gestures (rotation)</div>
        <div class="TargetContainer" id="targetContainer">
            <div id="target" draggable="false"></div>
        </div>
        <div id="targetFooter">&nbsp;</div>
    </div>
</body>
</html>

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

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

 

html,body {
    overflow: hidden;
    position: relative;
    height: 100%;
}

div #Container {
/*
This element permits no default touch behaviors.
A manipulation-blocking element is defined as an element that explicitly 
blocks direct manipulation via declarative markup, and instead fires gesture 
events such as MSGestureStart, MSGestureChange, and MSGestureEnd.
*/
    touch-action: none;
    display: -ms-grid;
    -ms-grid-rows: 200px 1fr 50px;
    -ms-grid-columns: 1fr;
    overflow: hidden;
    position: absolute;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}

div #targetTitle {
    touch-action: none;
    -ms-grid-row: 1;
    -ms-grid-column: 1;
    background-color: black;
    color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
    font-family: 'Segoe UI';
    font-size: large;
}
div #targetContainer {
    touch-action: none;
    -ms-grid-row: 2;
    -ms-grid-column: 1;
    background-color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}
div #targetFooter {
    touch-action: none;
    -ms-grid-row: 3;
    -ms-grid-column: 1;
    background-color: black;
    color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
    font-family: 'Segoe UI';
    font-size: large;
}

div #target {
    -ms-transform-origin: 0px 0px;
    position: absolute;
    width: 300px;
    height: 300px;
    background-color: black;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}

アプリを初期化する

アプリの起動時のターゲット、ターゲットのコンテナー、ターゲットへの操作の処理を設定します。

ここではコンテナー内のターゲット要素 (およびその他の UI オブジェクト) を初期化し、操作のハンドラーを設定します。

/// <summary> 
/// Initializes the target and manipulation handling.
/// </summary>
function initialize() {
    var container = document.getElementById("targetContainer");
    var target = document.getElementById("target");
    var title = document.getElementById("targetTitle");
    var footer = document.getElementById("targetFooter");
    // Set the height of the target container for initial positioning of the target.
    var containerHeight = window.innerHeight - title.clientHeight - footer.clientHeight;
    container.style.height = containerHeight + "px";
    // Set the initial position of the target.
    target.style.msTransform = (new MSCSSMatrix()).
        translate((container.clientWidth - parseInt(target.clientWidth)) / 2.0,
        (containerHeight - parseInt(target.clientHeight)) / 2.0);
    // Configure manipulation handling.
    var manipulable = new Manipulator.ManipulationManager();
    // The configuration function can support all manipulations.
    // For this example, we limit manipulation support to rotation with inertia.
    manipulable.configure(false,
                          true, // Rotation.
                          false,
                          true, // Inertia.
                          1,
                          0,
                          {
                              x: (container.clientWidth - parseInt(target.clientWidth)) / 2.0,
                              y: (containerHeight - parseInt(target.clientHeight)) / 2.0
                          });
    manipulable.setElement(target);
    manipulable.setParent(container);
    // Handler for transforms related to the manipulation.
    manipulable.registerMoveHandler({
        x: (container.clientWidth / 2.0),
        y: (containerHeight / 2.0)
    }, Manipulator.ManipulationManager.FixPivot.MoveHandler);
}

ポインター入力を処理してジェスチャ認識エンジンを構成する

この例では、基本的なラッパー クラス (InputProcessor) を使ってポインター イベント ハンドラーとポインター入力を使う GestureRecognizer オブジェクトを一緒に定義します。

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

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

ヒント  この例では、ジェスチャ認識エンジンに 1 つのオブジェクトだけが関連付けられています。多数の操作対象オブジェクトがあるアプリ (ジグソー パズルなど) の場合は、ターゲット オブジェクトでポインター入力が検出されたときにだけジェスチャ認識エンジンを動的に作ることを検討してください。ジェスチャ認識エンジンは、操作が完了したら破棄できます (その例については、入力: インスタンス化できるジェスチャのサンプルに関するページをご覧ください)。ジェスチャ認識エンジンの作成と破棄のオーバーヘッドを避けるには、初期化時にジェスチャ認識エンジンの小規模なプールを作り、必要に応じてそれらを動的に割り当てます。

 

ここで、ジェスチャ認識エンジン (_gestureRecognizer) は、すべてのポインター イベントとジェスチャ イベントをリッスンして処理します。

/// <summary> 
/// InputProcessor is a thin wrapper for pointer event handling and gesture detection.
/// Defines an InputProcessor class that takes all pointer event data and feeds it to
/// a GestureRecognizer for processing of the manipulation gestures 
/// as configured in ManipulationManager.js.
/// </summary>
(function () {
    "use strict";
    WinJS.Namespace.define("Manipulator", {
        InputProcessor: WinJS.Class.define(function () {
            // Constructor.
            this._gestureRecognizer = new Windows.UI.Input.GestureRecognizer();
            this._downPoint = null;
            this._lastState = null;
        }, {
            // Instance members.
            element: {
                /// <summary> 
                /// The manipulable element.
                /// </summary>
                get: function () {
                    if (!this._element) {
                        return null;
                    }
                    return this._element;
                },
                set: function (value) {
                    this._element = value;
                    this._setupElement();
                }
            },
            parent: {
                /// <summary> 
                /// The container that defines the coordinate space used
                /// for transformations during manipulation of the target.
                /// </summary>
                get: function () {
                    if (!this._parent) {
                        return null;
                    }
                    return this._parent;
                },
                set: function (value) {
                    this._parent = value;
                }
            },
            getRecognizer: function () {
                /// <summary>
                /// The gesture recognition object.
                /// </summary>
                return this._gestureRecognizer;
            },
            getDown: function () {
                /// <summary>
                /// The pointer data for the pointerdown event.
                /// </summary>
                return this._downPoint;
            },
            _setupElement: function () {
                /// <summary> 
                /// Declare the event listeners for the pointer events on the target.
                /// </summary>
                var that = this;
                this._element.addEventListener("pointerdown",
                    function (evt) { Manipulator.InputProcessor._handleDown(that, evt); },
                    false);
                this._element.addEventListener("pointermove",
                    function (evt) { Manipulator.InputProcessor._handleMove(that, evt); },
                    false);
                this._element.addEventListener("pointerup",
                    function (evt) { Manipulator.InputProcessor._handleUp(that, evt); },
                    false);
                this._element.addEventListener("pointercancel",
                    function (evt) { Manipulator.InputProcessor._handleCancel(that, evt); },
                    false);
                this._element.addEventListener("wheel",
                    function (evt) { Manipulator.InputProcessor._handleMouse(that, evt); },
                    false);
            }
        }, {
            // Static members.
            _handleDown: function (that, evt) {
                /// <summary> 
                /// Handler for the pointerdown event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._element.setPointerCapture(pp.pointerId);
                that._gestureRecognizer.processDownEvent(pp);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();

                // Capture the pointer location for this event.
                that._downPoint = { x: pp.position.x, y: pp.position.y };
            },
            _handleMove: function (that, evt) {
                /// <summary> 
                /// Handler for the pointermove event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pps = evt.getIntermediatePoints(that._parent);
                that._gestureRecognizer.processMoveEvents(pps);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleUp: function (that, evt) {
                /// <summary> 
                /// Handler for the pointerup event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._gestureRecognizer.processUpEvent(pp);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleCancel: function (that, evt) {
                /// <summary> 
                /// Handler for the pointercancel event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                that._gestureRecognizer.completeGesture();

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleMouse: function (that, evt) {
                /// <summary> 
                /// Handler for the mouse wheel event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._gestureRecognizer.processMouseWheelEvent(pp, evt.shiftKey, evt.ctrlKey);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
                evt.preventDefault();
            }
        })
    });
})();

操作を処理する

ここでは操作マネージャー クラス (ManipulationManager) を使って、操作の動作と、GestureRecognizer オブジェクトの制限を定義します。これは、前の手順で説明した、InputProcessor (_inputProcessor) で定義されているオブジェクトです。

/// <summary> 
/// ManipulationManager is the manipulation processing engine for the 
/// GestureRecognizer object defined in InputProcessor.js.
/// Different components and behaviors of manipulation (rotate, translate, zoom, 
/// and inertia) can be enabled, disabled, and customized as required.
/// </summary>
(function () {
    "use strict";
    WinJS.Namespace.define("Manipulator", {
        ManipulationManager: WinJS.Class.define(function () {
            // Constructor.
            // Create an input processor.
            this._inputProcessor = new Manipulator.InputProcessor();
            // Initialize the manipulation movement and end handlers.
            this._endHandler = null;
            this._moveHandler = null;
            // Create the transform matrices used for manipulating
            // and resetting the target.
            this._currentTransform = new MSCSSMatrix();
            this._initialTransform = new MSCSSMatrix();
            // Initialize the transform matrices values.
            this._initialTransformParams = {
                translation: { x: 0, y: 0 },
                rotation: 0,
                scale: 1
            };
            this._currentTransformParams = {
                translation: { x: 0, y: 0 },
                rotation: 0,
                scale: 1
            };
        }, {
            // Instance members.
            configure: function (scale, rotate, translate, inertia,
                                initialScale, initialRotate, initialTranslate) {
                /// <summary> 
                /// Define the behaviors of the ManipulationManager object.
                /// </summary>
                /// <param name="scale" type="Boolean">
                /// True if scaling is enabled.
                /// </param>
                /// <param name="rotate" type="Boolean">
                /// True if rotation is enabled.
                /// </param>
                /// <param name="translate" type="Boolean">
                /// True if translation is enabled.
                /// </param>
                /// <param name="inertia" type="Boolean">
                /// True if inertia is enabled.
                /// </param>
                /// <param name="initialScale" type="Number">
                /// The initial scale factor.
                /// </param>
                /// <param name="initialRotate" type="Number">
                /// The initial rotation value.
                /// </param>
                /// <param name="initialTranslate" type="Object">
                /// The initial translation values (x,y).
                /// </param>

                // Get the GestureRecognizer associated with this manipulation manager.
                var gr = this._inputProcessor.getRecognizer();
                // Set the manipulations supported by the GestureRecognizer if the
                // interaction is not already being processed.
                if (!gr.isActive) {
                    var settings = 0;
                    if (scale) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationScale;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationScaleInertia;
                        }
                    }
                    if (rotate) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationRotate;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationRotateInertia;
                        }
                    }
                    if (translate) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationTranslateX |
                            Windows.UI.Input.GestureSettings.manipulationTranslateY;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationTranslateInertia;
                        }
                    }

                    // Cache a reference to the current object.
                    var that = this;

                    // If any manipulation is supported, declare the manipulation event listeners.
                    if (scale || rotate || translate) {
                        gr.addEventListener('manipulationstarted',
                            function (evt) { Manipulator.ManipulationManager._manipulationStarted(that, evt); },
                            false);
                        gr.addEventListener('manipulationupdated',
                            function (evt) { Manipulator.ManipulationManager._manipulationUpdated(that, evt); },
                            false);
                        gr.addEventListener('manipulationended',
                            function (evt) { Manipulator.ManipulationManager._manipulationEnded(that, evt); },
                            false);
                    }

                    gr.gestureSettings = settings;

                    // Initialize the transform matrices.
                    this._currentTransformParams.scale = initialScale;
                    this._currentTransformParams.rotation = initialRotate;
                    this._currentTransformParams.translation = initialTranslate;

                    this._initialTransformParams.scale = initialScale;
                    this._initialTransformParams.rotation = initialRotate;
                    this._initialTransformParams.translation = initialTranslate;

                    // Set the transformation values.
                    if (initialRotate) {
                        this._initialTransform = this._initialTransform.rotate(initialRotate);
                    }
                    else {
                        this._currentTransformParams.rotation = 0;
                        this._initialTransformParams.rotation = 0;
                    }
                    if (initialTranslate) {
                        this._initialTransform = this._initialTransform.translate(initialTranslate.x, initialTranslate.y);
                    }
                    else {
                        this._currentTransformParams.translation = { x: 0, y: 0 };
                        this._initialTransformParams.translation = { x: 0, y: 0 };
                    }
                    if (initialScale) {
                        this._initialTransform = this._initialTransform.scale(initialScale);
                    }
                    else {
                        this._currentTransformParams.scale = 1;
                        this._initialTransformParams.scale = 1;
                    }

                    this._currentTransform = this._initialTransform;
                }
            },
            setElement: function (elm) {
                /// <summary> 
                /// Set the manipulable object.
                /// </summary>
                /// <param name="elm" type="Object">
                /// The object that supports manipulation.
                /// </param>
                this._inputProcessor.element = elm;
                // Set the transform origin for rotation and scale manipulations.
                this._inputProcessor.element.style.msTransformOrigin = "0 0";
            },
            setParent: function (elm) {
                /// <summary> 
                /// Set the parent of the manipulable object.
                /// </summary>
                /// <param name="elm" type="Object">
                /// The parent of the object that supports manipulation.
                /// </param>
                this._inputProcessor.parent = elm;
            },
            registerEndHandler: function (handler) {
                /// <summary> 
                /// Register handler to be called after the manipulation is complete.
                /// </summary>
                /// <param name="handler" type="Function">
                /// The manipulationended event handler.
                /// </param>
                this._endHandler = handler;
            },
            registerMoveHandler: function (arg, handler) {
                /// <summary> 
                /// Register handler to be called when manipulation is under way.
                /// </summary>
                /// <param name="args">
                /// Arguments passed to the move handler function.
                /// </param>
                /// <param name="handler" type="Function">
                /// The manipulationupdated event handler.
                /// </param>
                this._moveHandlerArg = arg;
                this._moveHandler = handler;
            },
            resetAllTransforms: function () {
                /// <summary> 
                /// Reset the ManipulationManager object to its initial state.
                /// </summary>

                // Check that the element has been registered before before attempting to reset.
                if (this._inputProcessor.element) {
                    // Reapply the initial transform
                    this._inputProcessor.element.style.transform = this._initialTransform.toString();
                    this._currentTransform = this._initialTransform;

                    // Reset the current transform parameters to their initial values.
                    this._currentTransformParams.translation = this._initialTransformParams.translation;
                    this._currentTransformParams.rotation = this._initialTransformParams.rotation;
                    this._currentTransformParams.scale = this._initialTransformParams.scale;
                }
            },

            _applyMotion: function (pivot, translation, rotation, scaling) {
                /// <summary> 
                /// Apply the manipulation transform to the target.
                /// </summary>
                /// <param name="pivot" type="Object">
                /// The X,Y values for the rotation and scaling pivot point.
                /// </param>
                /// <param name="translation" type="Object">
                /// The X,Y values for the translation delta.
                /// </param>
                /// <param name="rotation" type="Number">
                /// The angle of rotation.
                /// </param>
                /// <param name="scaling" type="Number">
                /// The scaling factor.
                /// </param>

                // Create the transform, apply parameters, and multiply by the current transform matrix.
                var transform = new MSCSSMatrix().translate(pivot.x, pivot.y).
                    translate(translation.x, translation.y).
                    rotate(rotation).
                    scale(scaling).
                    translate(-pivot.x, -pivot.y).multiply(this._currentTransform);

                this._inputProcessor.element.style.transform = transform.toString();
                this._currentTransform = transform;
            },

            _updateTransformParams: function (delta) {
                /// <summary> 
                /// Update the current transformation parameters based on the new delta.
                /// </summary>
                /// <param name="that" type="Object">
                /// The change in rotation, scaling, and translation.
                /// </param>
                this._currentTransformParams.translation.x = this._currentTransformParams.translation.x + delta.translation.x;
                this._currentTransformParams.translation.y = this._currentTransformParams.translation.y + delta.translation.y;
                this._currentTransformParams.rotation = this._currentTransformParams.rotation + delta.rotation;
                this._currentTransformParams.scale = this._currentTransformParams.scale * delta.scale;
            }
        }, {
            // Static members.
            _manipulationStarted: function (that, evt) {
                /// <summary> 
                /// The manipulationstarted event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                Manipulator.ManipulationManager._manipulationHelper(that, evt);
            },
            _manipulationUpdated: function (that, evt) {
                /// <summary> 
                /// The manipulationupdated event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                Manipulator.ManipulationManager._manipulationHelper(that, evt);
            },
            _manipulationEnded: function (that, evt) {
                /// <summary> 
                /// The manipulationended event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                // Pass the event to the manipulation helper function.
                Manipulator.ManipulationManager._manipulationHelper(that, evt);

                // Call the manipulationended handler, if registered.
                if (that._endHandler) {
                    that._endHandler();
                }
            },
            _manipulationHelper: function (that, evt) {
                /// <summary> 
                /// Helper function for calculating and applying the transformation parameter deltas.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>

                if (evt.delta) {
                    // Rotation/scaling pivot point.
                    var pivot = { x: evt.position.x, y: evt.position.y };

                    // Translation values.
                    var translation = { x: evt.delta.translation.x, y: evt.delta.translation.y };

                    // Rotation angle.
                    var rotation = evt.delta.rotation;

                    // Scale factor.
                    var scale = evt.delta.scale;

                    // Group the transformation parameter deltas.
                    var delta = {
                        pivot: pivot,
                        translation: translation,
                        rotation: rotation,
                        scale: scale
                    };

                    // Apply the manipulation movement constraints.
                    if (that._moveHandler) {
                        delta = that._moveHandler(that._moveHandlerArg, delta, that._currentTransformParams, that._currentTransform);
                    }

                    // Update the transformation parameters with fresh deltas.
                    that._updateTransformParams(delta);

                    // Apply the transformation.
                    that._applyMotion(delta.pivot, delta.translation, delta.rotation, delta.scale);
                }
            },
            FixPivot: WinJS.Class.define(function () {
            /// <summary>
            /// Constrain the center of manipulation (or pivot point) to a set of X,Y coordinates,  
            /// instead of the centroid of the pointers associated with the manipulation.
            /// <param name="pivot" type="Object">
            /// The pivot coordinates for the ManipulationManager object.
            /// </param>
            /// <param name="delta" type="Object">
            /// The transformation parameter deltas (pivot, delta, rotation, scale).
            /// </param>
            /// </summary>
            }, {
            }, {
                MoveHandler: function (pivot, delta) {
                    delta.pivot = pivot;
                    return delta;
                }
            }),
        })
    });
})();

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

完全な例

操作ジェスチャのコード一式」をご覧ください。

要約と次のステップ

このクイック スタートでは、JavaScript を使った Windows ストア アプリでの操作ジェスチャ イベントの処理について説明しました。

操作ジェスチャはパン、並べ替え、または移動のためのスライド、ズーム、回転などの複雑な対話式操作のサポートと管理に役立ちます。

さらに複雑なジェスチャ処理の例については、入力: インスタンス化できるジェスチャのサンプルに関するページをご覧ください。

  このサンプルは、カスタムの対話式操作に関しては Windows のタッチ言語のガイダンスに準拠していません。説明を目的として一部の静的ジェスチャは再定義されています。

 

静的対話式操作 (スライド、スワイプ、回転、ピンチ、ストレッチなど) の管理について詳しくは、「クイック スタート: 静的ジェスチャ」をご覧ください。

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

関連トピック

開発者向け

ユーザー操作への応答

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

クイック スタート: ポインター

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

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

デザイナー向け

タッチ操作の設計