Guida introduttiva: Gesti di manipolazione (HTML)

[ Questo articolo è rivolto agli sviluppatori per Windows 8.x e Windows Phone 8.x che realizzano app di Windows Runtime. Gli sviluppatori che usano Windows 10 possono vedere Documentazione aggiornata ]

Puoi personalizzare l'esperienza utente per i gesti di manipolazione descritti nel linguaggio per il tocco di Windows, ad esempio scorrimento, scorrimento rapido, avvicinamento e allontanamento delle dita e rotazione. A questo scopo, gestisci gli eventi di Windows Runtime relativi ai gesti nella tua app di che usa JavaScript.

La maggior parte delle app elabora i gesti (rotazione, zoom e trascinamento) e si limita a passare i dati del puntatore non elaborati per il rilevamento dei gesti. In questo esempio usiamo i dati del puntatore non elaborati per supportare la gestione e l'elaborazione di gesti statici. Ciò estende il modello di interazione dell'app e si basa sugli eventi di base relativi al puntatore descritti in Guida introduttiva: Puntatori.

Aggiornamenti per Windows 8.1: In Windows 8.1 vengono introdotti diversi aggiornamenti e miglioramenti alle API di input tramite puntatore. Per altre informazioni, vedi Modifiche delle API per Windows 8.1.

Se non hai familiarità con lo sviluppo di app mediante JavaScript,: Leggi questi argomenti per imparare a conoscere le tecnologie qui descritte.

Creare la prima app con JavaScript

Roadmap per app in JavaScript

Scopri di più sugli eventi in Guida introduttiva: Aggiunta di controlli HTML e gestione di eventi

Funzionalità delle app dall'inizio alla fine:

Per conoscere meglio questa funzionalità, vedi gli argomenti della serie Funzionalità dell'app dall'inizio alla fine

Interazioni con l'utente, dall'inizio alla fine (HTML)

Personalizzazione delle interazioni con l'utente, dall'inizio alla fine (HTML)

Linee guida per l'esperienza utente:

Le raccolte di controlli della piattaforma (HTML e XAML) forniscono un'esperienza di interazione utente completa, che include interazioni standard, effetti fisici animati e feedback visivo. Se non hai l'esigenza di supportare interazioni personalizzate, usa questi controlli predefiniti.

Se i controlli della piattaforma non sono sufficienti, queste linee guida ti aiuteranno a offrire un'esperienza di interazione coinvolgente e Immersive coerente tra le diverse modalità di input. Queste linee guida sono incentrate principalmente sull'input tocco, ma sono rilevanti anche per input di tipo tocco, mouse, tastiera e stilo.

Esempi: Per esaminare questa funzionalità in azione, vedi gli esempi di app.

Esempio di personalizzazione delle interazioni con l'utente, dall'inizio alla fine

Input: Esempio di gestione degli eventi relativi al puntatore DOM

Input: Esempio di manipolazioni e gesti (JavaScript)

Obiettivo: Viene illustrato come rilevare, gestire ed elaborare gesti di manipolazione usando interazioni tramite tocco, mouse, penna/stilo ed eventi di Windows Runtime relativi ai gesti.

Prerequisiti

Vedi Guida introduttiva: Puntatori, Guida introduttiva: Gesti DOM e manipolazioni e Guida introduttiva: Gesti statici.

In questa guida introduttiva si suppone che tu sia in grado di creare con Javascript un'app di base che usi il modello Libreria Windows per JavaScript.

Per completare questa esercitazione, devi:

Che cosa sono gli eventi relativi ai gesti?

Un gesto è l'atto fisico o il movimento eseguito su o dal dispositivo di input, ad esempio uno o più dita su una superficie di tocco, un digitalizzatore di penna/stilo, il mouse e così via. Queste interazioni naturali vengono mappate a operazioni su elementi nel sistema e nell'app. Per altre informazioni, vedi Gesti, manipolazioni e interazioni.

Nella tabella seguente sono elencati i gesti di manipolazione descritti in questa guida introduttiva. Per informazioni sul supporto dei gesti statici, ad esempio il tocco e la pressione prolungata, vedi Guida introduttiva: Gesti statici.

GestoDescrizione
ScorrimentoGesto scorrimento

Uno o più contatti che si spostano oltre una soglia di distanza.

Se la panoramica non è abilitata e il contatto iniziale è entro i confini di un elemento, lo scorrimento determina lo spostamento dell'elemento.

Se la panoramica è abilitata, il contatto iniziale è entro i confini di un elemento e la direzione di scorrimento è perpendicolare all'asse delle panoramica, lo scorrimento determina lo spostamento dell'elemento. In caso contrario viene avviata la panoramica.

  • Stato iniziale: uno o più contatti rilevati.
  • Movimento: il gesto di trascinamento o scorrimento supera la soglia di distanza.
  • Stato finale: ultimo contatto rilasciato o terminato.
Scorrimento rapidoGesto scorrimento rapido

Uno o più contatti che si spostano entro una soglia di distanza (gesto scorrimento breve). Lo scorrimento rapido non è un gesto basato sulla velocità o sul tempo.

Se la panoramica non è abilitata e il contatto iniziale avviene entro i confini di un elemento, lo scorrimento rapido determina lo spostamento dell'elemento.

Se la panoramica è abilitata, il contatto iniziale avviene entro i confini di un elemento e la direzione di scorrimento rapido è perpendicolare all'asse delle panoramica, lo scorrimento rapido determina la selezione dell'elemento. In caso contrario, lo scorrimento rapido avvia la panoramica.

  • Stato iniziale: uno o più contatti rilevati.
  • Movimento: il gesto di trascinamento o scorrimento non supera la soglia di distanza.
  • Stato finale: ultimo contatto rilasciato o terminato.
Avvicinamento e allontanamento delle ditaGesto avvicinamento e allontanamento delle dita

Due o più contatti che convergono o divergono per lo zoom avanti o indietro rispettivamente.

Questo gesto viene in genere usato per ridimensionare un oggetto, eseguire lo zoom avanti o indietro su una vista o per lo zoom semantico.

  • Stato iniziale: due o più contatti rilevati entro il rettangolo di delimitazione di un oggetto.
  • Movimento: trascinamento o scorrimento con contatti convergenti o divergenti.
  • Stato finale: meno di due contatti rilevati.
RotazioneGesto rotazione

Ruotando due o più dita, è possibile far ruotare un oggetto sullo schermo. Ruotare il dispositivo per far ruotare l'intero schermo.

Due o più contatti che si muovono con un movimento circolare attorno a un centro (o punto) di rotazione.

Questo gesto viene in genere usato per ruotare un oggetto.

  • Stato iniziale: due o più contatti rilevati entro il rettangolo di delimitazione di un oggetto.
  • Movimento: trascinamento o scorrimento di uno o più contatti in un movimento circolare.
  • Stato finale: meno di due contatti rilevati.

Per altre informazioni sui gesti e sulla correlazione con il linguaggio per il tocco di Windows 8, vedi Progettazione delle interazioni tramite tocco.

 

Importante  Se implementi un supporto personalizzato per le interazioni, tieni presente che gli utenti si aspettano un'esperienza intuitiva che include l'interazione diretta con gli elementi dell'interfaccia utente della tua app. Ti consigliamo di modellare le tue interazioni personalizzate sulle raccolte di controlli della piattaforma (HTML e XAML) per garantire la coerenza e l'intuitività. I controlli inclusi in queste librerie forniscono un'esperienza di interazione utente completa che include le interazioni standard, gli effetti fisici animati, il feedback visivo e l'accessibilità. Crea interazioni personalizzate solo in presenza di un requisito chiaro e ben definito e qualora le interazioni di base non siano in grado di supportare il tuo scenario.

 

Creare l'interfaccia utente

Questo esempio illustra come abilitare un singolo gesto di manipolazione, ovvero la rotazione, su un elemento di interfaccia utente di base. Un quadrato (target) funge da oggetto di destinazione per il rilevamento e l'input del puntatore. I dati del puntatore vengono passati a un oggetto GestureRecognizer che elabora i dati provenienti da un gesto di rotazione per creare una manipolazione della rotazione con il comportamento di inerzia standard.

L'app offre le seguenti funzionalità di interazione utente:

  • Rotazione: ruota l'oggetto con inerzia quando i contatti del puntatore vengono terminati. Questo comportamento di interazione è conforme alle linee guida per la risposta visiva e alle raccomandazioni del linguaggio per il tocco di Windows. In base a queste raccomandazioni, il gesto di rotazione deve essere limitato alla rotazione degli elementi dell'interfaccia utente. Nota  Questo esempio può essere facilmente modificato per il supporto del gesto di trascinamento e zoom. Illustreremo questo gesto più avanti in questa guida introduttiva.  

HTML per questo esempio.

<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 (Cascading Style Sheets) per questo esempio.

Nota  Gli eventi puntatore non vengono generati durante un'interazione di tipo panoramica o zoom. Puoi disabilitare la panoramica e lo zoom in un'area tramite le proprietà msTouchAction, overflow e -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;
}

Inizializzare l'app

Imposta la destinazione, il suo contenitore e la gestione della manipolazione della destinazione all'avvio dell'app.

In questo esempio inizializziamo l'elemento di destinazione (e altri oggetti di interfaccia utente) nel contenitore e configuriamo un gestore per le manipolazioni.

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

Gestire l'input del puntatore e configurare il riconoscitore dei gesti

Per questo esempio usiamo una classe wrapper di base (InputProcessor) per definire i gestori degli eventi del puntatore insieme all'oggetto GestureRecognizer che utilizza l'input del puntatore.

Nella maggior parte dei casi è consigliabile ottenere informazioni sul puntatore mediante l'argomento dell'evento del gestore eventi del puntatore nel framework del linguaggio che hai scelto.

Se l'argomento dell'evento non espone i dettagli del puntatore richiesti dall'app, puoi ottenere l'accesso a dati del puntatore estesi dall'argomento dell'evento tramite i metodi getCurrentPoint e getIntermediatePoints o le proprietà currentPoint e intermediatePoints. Ti consigliamo di usare i metodi getCurrentPoint e getIntermediatePoints perché puoi specificare il contesto dei dati del puntatore.

Suggerimento  Per questo esempio, solo un oggetto è associato a un riconoscitore di gesti. Se l'app contiene un numero elevato di oggetti manipolabili, ad esempio un puzzle, prova a creare dinamicamente un riconoscitore di gesti solo quando viene rilevato l'input del puntatore su un oggetto di destinazione. Il riconoscitore di gesti può essere eliminato al termine della manipolazione. Per un esempio, vedi Input: Esempio di gesti istanziabili. Per evitare il sovraccarico delle attività di creazione ed eliminazione, crea un piccolo pool di riconoscitori di gesti in fase di inizializzazione e assegnali dinamicamente in base alle necessità.

 

In questo caso, il riconoscitore di gesti (_gestureRecognizer) rileva e gestisce tutti gli eventi del puntatore e dei gesti.

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

Elaborare la manipolazione

In questo esempio usiamo una classe di gestione della manipolazione (ManipulationManager) per definire i comportamenti e i vincoli della manipolazione per l'oggetto GestureRecognizer definito nell'oggetto InputProcessor (_inputProcessor) nel passaggio precedente.

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

Per i link a esempi più complessi, vedi gli Argomenti correlati alla fine della pagina.

Esempio completo

Vedi il codice completo per i gesti di manipolazione.

Riepilogo e passaggi successivi

In questa Guida introduttiva hai imparato i concetti relativi alla gestione degli eventi relativi ai gesti di manipolazione nelle app di Windows Store scritte in JavaScript.

I gesti di manipolazione sono utili per supportare e gestire interazioni complesse, come lo scorrimento per eseguire una panoramica, la ridisposizione o spostamento, lo zoom e la rotazione.

Per un esempio più complesso di gestione dei gesti, vedi Input: Esempio di gesti istanziabili.

Nota  Questo esempio non è conforme alle linee guida del linguaggio per il tocco di Windows per quanto concerne le interazioni personalizzate. Alcuni dei gesti statici sono stati ridefiniti per scopi formativi.

 

Per la gestione di interazioni statiche, ad esempio scorrimento, scorrimento rapido, avvicinamento e allontanamento delle dita e rotazione, vedi Guida introduttiva: Gesti statici.

Per altre info sul linguaggio per il tocco di Windows 8, vedi Progettazione delle interazioni tramite tocco.

Argomenti correlati

Sviluppatori

Risposta alle interazioni degli utenti

Sviluppo di app di Windows Store (JavaScript e HTML)

Guida introduttiva: Puntatori

Guida introduttiva: Gesti e manipolazioni DOM

Guida introduttiva: Gesti statici

Progettisti

Progettazione delle interazioni tramite tocco