快速入門:操作手勢 (HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

您可以自訂 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,以適用於 JavaScript 的 Windows Library 範本建立基本的應用程式。

若要完成這個教學課程,您需要:

什麼是手勢事件?

手勢是在輸入裝置上或由輸入裝置所執行的實際動作。這包括觸控表面上的一或多根手指、畫筆/手寫筆數位板、滑鼠等。這些自然的互動都會對應到系統和您應用程式中元素的作業。 如需詳細資訊,請參閱手勢、操作以及互動

下表描述本快速入門中涵蓋的操作手勢。如需支援的靜態手勢 (例如點選和按住不放),請參閱快速入門:靜態手勢

手勢說明
滑動滑動手勢

移動超過距離閾值的一或多個接觸點。

如果未啟用移動瀏覽且初始接觸點位於元素的範圍內,滑動會移動該元素。

如果啟用移動瀏覽,初始接觸點位於元素的範圍內而且滑動方向與移動瀏覽軸垂直,則滑動會移動該元素。否則,會初始化移動瀏覽。

  • 進入狀態:偵測到一或多個接觸點。
  • 動作:拖曳/滑動超過距離閾值。
  • 結束狀態:放開或終止最後一個接觸點。
撥動撥動手勢

在距離閾值內移動的一或多個接觸點 (短距離滑動手勢)。撥動不是以速度或時間為基礎的手勢。

如果應用程式未啟用移動瀏覽且初始接觸點位於元素的範圍內,撥動會移動該元素。

如果應用程式啟用移動瀏覽,初始接觸點位於元素的範圍內而且撥動方向與移動瀏覽軸垂直,則撥動會選取該元素。否則,撥動會初始化移動瀏覽。

  • 進入狀態:偵測到一或多個接觸點。
  • 動作:拖曳/滑動未超過距離閾值。
  • 結束狀態:放開或終止最後一個接觸點。
捏合和延展捏合和伸展手勢

分別以聚合或分開方式放大或縮小的兩個以上接觸點。

通常用來調整物件的大小、在檢視中放大或縮小,或者用於語意式縮放。

  • 進入狀態:在物件的週框矩形內偵測到兩個以上接觸點。
  • 動作:利用接觸點聚合或分開拖曳/滑動。
  • 結束狀態:偵測到的接觸點少於兩個。
轉動轉動手勢

旋轉兩根或更多手指讓物件旋轉。旋轉裝置本身即可旋轉整個螢幕。

以畫圓的動作繞著旋轉中心 (或點) 移動的兩個以上接觸點。

通常用來旋轉物件。

  • 進入狀態:在物件的週框矩形內偵測到兩個以上接觸點。
  • 動作:以畫圓的動作拖曳/滑動一或多個接觸點。
  • 結束狀態:偵測到的接觸點少於兩個。

如需這些手勢及它們如何與 Windows 8 觸控語言相關的詳細資訊,請參閱觸控互動設計

 

重要  如果您實作自己的互動支援,請牢記使用者所期待的是與應用程式 UI 元素直接互動的直覺式體驗。 建議您在平台控制項程式庫 (HTMLXAML) 模型化您的自訂互動,以保持一致和可探索的 UI 體驗。這些程式庫中的控制項提供完整的使用者互動體驗,包含標準互動、動畫物理效果、視覺化回饋及協助工具。只有在需求明確且定義清楚,而且沒有基本的互動可以支援您的情況時,才建立自訂互動。

 

建立 UI

這個範例示範如何在基本 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 方法。

秘訣  在此範例中,只有一個與手勢辨識器關聯的物件。如果您的應用程式包含大量可操作的物件 (例如拼圖),請只有在目標物件上偵測到指標輸入時,才考慮動態建立手勢辨識器。操作完成時,即可摧毀手勢辨識器 (如需這類操作的範例,請參閱輸入:可具現化手勢範例)。若要避免建立和摧毀手勢辨識器時產生額外負荷,請在初始化時建立小型的手勢辨識器集區,並視需要動態加以指派。

 

在這裡,手勢辨識器 (_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 手勢與操作

快速入門:靜態手勢

設計人員

觸控互動設計