Início rápido: gestos de manipulação (HTML)

[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente]

Você pode personalizar a experiência do usuário de para os gestos de manipulação descritos na linguagem de toque do Windows, como deslizar, passar o dedo, girar, pinçar e ampliar. Para fazer isso, manipule os eventos de gesto do Tempo de Execução do Windows em seu aplicativo em JavaScript.

A maioria dos aplicativos processa gestos (girar, aplicar zoom e arrastar) e faz pouco uso dos dados de ponteiro brutos, com exceção de repassá-los para a detecção do gesto. Neste exemplo, usamos os dados de ponteiro bruto no suporte de manipulação e processamento de gestos. Isso estende o modelo de interação do seu aplicativo, com base nos eventos de ponteiro básicos descritos em Início rápido: ponteiros.

Atualizações para Windows 8.1: O Windows 8.1 introduz uma série de atualizações e melhorias para as APIs de entrada de ponteiro. Para saber mais, veja Alterações de API para Windows 8.1.

Se você for iniciante no desenvolvimento de aplicativos em JavaScript: Leia estes tópicos para se familiarizar com as tecnologias discutidas aqui.

Criar seu primeiro aplicativo em JavaScript

Mapa para aplicativos usando JavaScript

Saiba mais sobre eventos com o Guia de início rápido: adicionando controles HTML e manipulando eventos

Recursos de aplicativos, do início ao fim:

Explore esse recurso mais profundamente como parte da nossa série sobre recursos para aplicativos, do início ao fim

Interação do usuário, do início ao fim (HTML)

Personalização da interação do usuário, do início ao fim (HTML)

Diretrizes de experiência do usuário:

As bibliotecas de controle de plataforma (HTML e XAML) fornecem uma experiência de total interação do usuário, incluindo interações padrão, efeitos físicos animados e comentários visuais. Se não precisar de suporte para interação personalizada, use esses controles internos.

Se os controles de plataforma não forem suficientes, as diretrizes a seguir para interação do usuário podem ajudá-lo a proporcionar uma experiência de interação envolvente e imersiva, consistente entre os modos de entrada. Essas diretrizes têm como foco principal a entrada por toque, mas elas ainda são relevante para entrada por touchpad, mouse, teclado e caneta.

Exemplos: Veja essa funcionalidade em ação em nossos exemplos de aplicativos.

Exemplo de personalização da interação do usuário, do início ao fim

Entrada: amostra de manipulação de eventos de ponteiros DOM

Entrada: exemplo de manipulações e gestos (JavaScript)

Objetivo: Aprender a ouvir, manipular e processar gestos de manipulação usando entrada de interações por toque, mouse, caneta e eventos de gesto do Tempo de Execução do Windows.

Pré-requisitos

Reveja Guia de início rápido: ponteiros e Guia de início rápido: manipulações e gestos DOM e Guia de início rápido: gestos estáticos.

Nós supomos que você possa criar um aplicativo básico em JavaScript que use o modelo da Biblioteca do Windows para JavaScript.

Para completar este tutorial, você precisa:

O que são eventos de gesto?

Um gesto é uma ação ou movimento físico realizado no/pelo dispositivo de entrada. Isso pode incluir um ou mais dedos em uma superfície de toque, caneta digitalizadora, mouse, etc. Essas interações naturais são mapeadas para operações de elementos no sistema e no seu aplicativo. Para saber mais, veja Gestos, manipulações e interações.

A tabela a seguir identifica os gestos de manipulação abordados neste Guia de início rápido. Veja Guia de início rápido: gestos estáticos para saber sobre os gestos estáticos suportados, como tocar e manter pressionado.

GestoDescrição
DeslizarGesto de deslizar o dedo

Um ou mais contatos que se movem além de um limite de distância.

Se o movimento panorâmico não estiver habilitado e o contato inicial estiver dentro dos limites de um elemento, o deslizamento moverá o elemento.

Se o movimento panorâmico estiver habilitado, o contato inicial estiver dentro dos limites de um elemento e a direção de deslizamento estiver perpendicular ao eixo do movimento panorâmico, o deslizamento moverá o elemento. Caso contrário, o movimento panorâmico será iniciado.

  • Estado de entrada: um ou mais contatos detectados.
  • Movimento: arraste/deslizamento cruzam o limite da distância.
  • Estado de saída: último contato liberado ou encerrado.
Passar o dedoGesto de passar o dedo

Um ou mais contatos que se movem dentro de um limite de distância (um breve gesto de deslizamento). A passagem do dedo não é um gesto que depende de velocidade ou tempo.

Se o aplicativo não permitir movimento panorâmico e o contato inicial estiver dentro dos limites de um elemento, a passagem do dedo moverá o elemento.

Se o aplicativo permitir movimento panorâmico, o contato inicial estiver dentro dos limites de um elemento e a direção da passagem do dedo for perpendicular ao eixo do movimento panorâmico, a passagem do dedo selecionará o elemento. Caso contrário, a passagem do dedo iniciará o movimento panorâmico.

  • Estado de entrada: um ou mais contatos detectados.
  • Movimento: arraste/deslizamento não cruzam o limite da distância.
  • Estado de saída: último contato liberado ou encerrado.
Pinçar e ampliarGesto de pinçagem e ampliação

Dois ou mais contatos que convergem ou divergem para aumentar ou diminuir o zoom, respectivamente.

Normalmente usados para redimensionar um objeto, aumentar ou diminuir o zoom em uma exibição ou para Zoom Semântico.

  • Estado de entrada: dois ou mais contatos detectados dentro do retângulo delimitador de um objeto.
  • Movimento: arraste/deslizamento com contatos que convergem ou divergem.
  • Estado de saída: menos de dois contatos detectados.
VirarGesto de girar

Girar com dois ou mais dedos faz com que um objeto gire. Gire o dispositivo em si para girar a tela inteira.

Dois ou mais contatos que se movem circularmente em torno de um centro (ou ponto) de rotação.

Normalmente usado para girar um objeto.

  • Estado de entrada: dois ou mais contatos detectados dentro do retângulo delimitador de um objeto.
  • Movimento: arrastar/deslizar um ou mais contatos em movimento circular.
  • Estado de saída: menos de dois contatos detectados.

Para saber mais sobre esses gestos e como eles se relacionam à linguagem de toque do Windows 8, veja Design da interação por toque.

 

Importante  Se você implementar seu próprio suporte para interação, tenha em mente que os usuários esperam uma experiência intuitiva que envolva a interação direta com os elementos de interface do usuário do seu aplicativo. Recomendamos que você modele as interações personalizadas nas bibliotecas de controles de plataforma (HTML e XAML) para manter tudo consistente e detectável. Os controles nessas bibliotecas fornecem uma experiência de interação completa para o usuário, incluindo interações padrão, efeitos físicos animados, comentários visuais e acessibilidade. Crie interações personalizadas somente se houver uma exigência clara e bem definida e se nenhuma das interações básicas suportar o seu cenário.

 

Criar a interface do usuário

Este exemplo demonstra como habilitar um único gesto de manipulação, virar para girar, em um elemento de interface do usuário básico. Um quadrado (target) atua como objeto de destino para entrada e detecção do ponteiro. Os dados do ponteiro são transmitidos para um objeto GestureRecognizerque processa os dados de um gesto de girar para criar uma manipulação de rotação com comportamento de inércia padrão.

O aplicativo fornece a seguinte funcionalidade de interação do usuário:

  • Virar: gira o objeto, com inércia quando os contatos do ponteiro são encerrados. Esse comportamento de interação segue as Diretrizes de resposta visual e as recomendações de linguagem de toque do Windows. Essas recomendações determinam que o gesto de girar deve ser limitado à rotação dos elementos da IU. Observação  Este exemplo pode ser facilmente modificado para dar suporte a arrastar e aplicar zoom. Abordaremos esse assunto mais adiante neste guia de início rápido.  

Este é o HTML desse exemplo.

<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>

Estas são as CSS (Folhas de Estilos em Cascata) para este exemplo.

Observação  Eventos de ponteiro não são disparados durante uma interação de panorâmica ou zoom. Você pode desabilitar gestos de panorâmica e zoom por meio das propriedades msTouchAction, overflow e -ms-content-zooming da CSS.

 

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;
}

Inicializar o aplicativo

Configure o destino, seu contêiner e a manipulação do destino quando o aplicativo for iniciado.

Aqui inicializamos o elemento de destino (e outros objetos de interface do usuário) dentro do contêiner e configuramos um manipulador para manipulações.

/// <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);
}

Manipule a entrada do ponteiro e configure o reconhecedor de gestos

Para este exemplo, usamos uma classe wrapper básica (InputProcessor) para definir os manipuladores de eventos de ponteiro juntamente com o objeto GestureRecognizer que consome a entrada de ponteiro.

Na maioria dos casos, recomendamos que você obtenha informações sobre o ponteiro por meio do argumento de eventos dos manipuladores de eventos do ponteiro em sua estrutura de idioma escolhida.

Se o argumento não representar os detalhes de ponteiro exigidos pelo seu aplicativo, você poderá obter acesso a dados de ponteiro estendidos do argumento do evento por meio dos métodos getCurrentPoint e getIntermediatePoints ou das propriedades currentPoint e intermediatePoints. Nós recomendamos o uso dos métodos getCurrentPoint e getIntermediatePoints pois você pode especificar o contexto dos dados de ponteiro.

Dica  Para este exemplo, há apenas um objeto associado a um reconhecedor de gestos. Se o seu aplicativo tiver uma grande quantidade de objetos que podem ser manipulados (como um quebra-cabeça), considere criar dinamicamente um reconhecedor de gestos apenas quando a entrada do ponteiro é detectada em um objeto de destino. O reconhecedor de gestos pode ser destruído quando a manipulação é concluída (veja um exemplo em Entrada: exemplo de gestos instanciáveis). Para evitar a sobrecarga da criação e destruição de reconhecedores de gestos, crie um pequeno pool de reconhecedores de gestos na inicialização e atribua-os dinamicamente conforme necessário.

 

Aqui, o reconhecedor de gestos (_gestureRecognizer) ouve e manipula todos os eventos de ponteiro e de gesto.

/// <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();
            }
        })
    });
})();

Processe a manipulação.

Aqui, nós usamos uma classe gerenciadora de manipulações (ManipulationManager) para definir os comportamentos e restrições de manipulação do objeto GestureRecognizer. Esse é o objeto que foi definido em InputProcessor (_inputProcessor) descrito na etapa anterior.

/// <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;
                }
            }),
        })
    });
})();

Confira os Tópicos relacionados no final desta página para acessar links para exemplos mais complexos.

Exemplo completo

Veja Código completo de gestos de manipulação.

Resumo e próximas etapas

Neste Guia de início rápido, você aprendeu a manipular eventos de gestos em aplicativos da Windows Store criados em JavaScript.

Os gestos de manipulação são úteis para dar suporte a, e gerenciar, manipulações complexas como deslizar para criar movimento panorâmico ou reorganizar/mover, aplicar zoom e girar.

Veja Entrada: exemplo de gestos instanciáveis para obter um exemplo mais complexo de manipulação de gestos.

Observação  Este exemplo não adere às diretrizes para linguagem de toque do Windows no que se refere a interações personalizadas. Alguns dos gestos estáticos foram redefinidos para fins instrutivos.

 

Para gerenciar manipulações estáticas (como deslizar, passar o dedo, virar, pinçar e ampliar), veja Guia de início rápido: gestos estáticos.

Para saber mais sobre a linguagem de toque do Windows 8, veja Design da interação por toque.

Tópicos relacionados

Desenvolvedores

Respondendo à interação do usuário

Desenvolvendo aplicativos da Windows Store (JavaScript e HTML)

Guia de início rápido: ponteiros

Guia de início rápido: gestos e manipulações DOM

Guia de início rápido: gestos estáticos

Designers

Design de interação por toque