Aplicaciones de Windows
Contraer la tabla de contenido
Expandir la tabla de contenido

Inicio rápido: gestos estáticos (aplicaciones de la Tienda Windows con JavaScript y HTML)

Controla eventos de gestos básicos de Windows en tiempo de ejecución en una aplicación de la Tienda Windows con JavaScript para personalizar la experiencia del usuario para los gestos estáticos descritos en el lenguaje táctil de Windows 8 (como pulsación, doble pulsación, pulsar y sostener y pulsación derecha).

La mayoría de las aplicaciones procesa los gestos (pulsaciones, movimientos panorámicos, zoom, etc.) y no hace prácticamente nada con los datos de puntero sin procesar, salvo pasarlos a la detección de gestos. En este ejemplo, usamos estos datos de puntero sin procesar en favor del control y procesamiento de los gestos estáticos para ampliar el modelo de interacción de la aplicación y basarse en los eventos de puntero descritos en Inicio rápido: punteros.

Guía básica: ¿Qué relación tiene este tema con los demás? Consulta el tema sobre la guía básica para aplicaciones de la Tienda Windows con JavaScript.

Nota  Las bibliotecas de control de marco proporcionan una experiencia de interacción de usuario de Windows 8 completa, que incluye interacciones estándar, efectos físicos animados y comentarios visuales. Si no necesitas interacciones del usuario personalizadas, usa estos controles integrados. Si los controles del marco no son suficientes, las siguientes directrices para interacciones del usuario te pueden ayudar a proporcionar una experiencia de interacción atractiva y envolvente que sea coherente en todos los modos de entrada:

Objetivo: aprender a escuchar, controlar y procesar gestos estáticos mediante entradas de interacciones táctiles, del mouse, de lápiz o pluma y eventos de gestos de Windows en tiempo de ejecución.

Requisitos previos

Revisa los temas de inicio rápido: punteros y de inicio rápido: gestos y manipulaciones de DOM.

Damos por sentado que sabes crear una aplicación básica de la Tienda Windows con JavaScript que use la plantilla de Biblioteca de Windows para JavaScript.

Tiempo para finalizar: 30 minutos.

¿Qué son los eventos de gesto?

Un gesto es el acto físico o movimiento ejecutado en el dispositivo de entrada o por él (uno o varios dedos en una superficie táctil, un digitalizador de pluma o lápiz, un mouse, etc.). Estas interacciones naturales se asignan a operaciones en elementos tanto del sistema como de tu aplicación. Para más información, consulta el tema sobre gestos, manipulaciones e interacciones.

La siguiente tabla identifica los gestos estáticos de Windows 8 que se abordan en este inicio rápido.

GestoDescripción
Pulsación/doble pulsaciónJJ218355.touch_tap_primary(es-ar,WIN.10).png

Un único contacto que se libera o finaliza inmediatamente.

La pulsación sobre un elemento invoca esta acción principal.

Una doble pulsación son dos pulsaciones rápidas sucesivas, las cuales pueden controlarse según lo requiera la aplicación.

  • Estado de entrada: se ha detectado un contacto dentro de los límites rectangulares de un objeto.
  • Movimiento: ninguno.
  • Estado de salida: el contacto se libera o finaliza.
Pulsar y sostener/pulsación derechaJJ218355.touch_press_to_learn(es-ar,WIN.10).png

Un único contacto que no se mueve hasta que se supera un umbral de tiempo.

Pulsar y sostener hace que se muestre información detallada o elementos visuales didácticos (por ejemplo, información sobre herramientas o un menú contextual) sin confirmar una acción.

La pulsación derecha está estrechamente relacionada con el gesto de pulsar y sostener. El evento de pulsación derecha se desencadena cuando se libera el gesto de pulsar y sostener.

  • Estado de entrada: se ha detectado un contacto dentro de los límites rectangulares de un objeto.
  • Movimiento: ninguno.
  • Estado de salida: el contacto se libera o finaliza.

Para más información sobre estos gestos y cómo se relacionan con el lenguaje táctil de Windows 8, consulta el tema acerca del diseño de la interacción táctil.

 

Importante  Si implementas tu propia compatibilidad con la interacción, ten presente que los usuarios esperan una experiencia intuitiva en la que interactúen en forma directa con los elementos de la interfaz de usuario de tu aplicación. Te recomendamos que modeles tus interacciones personalizadas sobre la base de los controles de marco para que todo sea coherente y pueda detectarse. Crea únicamente interacciones personalizadas si existe un requisito claro y bien definido y no hay ninguna interacción básica que sea compatible con el escenario.

Crear la interfaz de usuario

Este ejemplo es una aplicación básica de preguntas y respuestas. Un cuadrado (inputBox) sirve de objeto de destino para detectar y procesar entradas de puntero y gestos estáticos. Todas las preguntas, pistas y respuestas se muestran dentro de este objeto.

La aplicación proporciona las siguientes funciones de interacción del usuario:

  • Doble pulsación: inicia y detiene las preguntas y el temporizador de la aplicación.
  • Pulsación: recorre las preguntas.
  • Pulsar y sostener: muestra un conjunto de pistas para la pregunta actual revelándolas de a una cada pocos segundos mientras se mantiene el contacto presionado. Este comportamiento de interacción cumple con las directrices para información visual y las recomendaciones del lenguaje táctil de Windows 8 que indican que el gesto de pulsar y sostener debe estar limitado a la visualización de la interfaz de usuario informativa.
  • pulsación derecha (o liberación de pulsar y sostener): cuando se levanta el contacto, muestra un elemento emergente que pregunta al usuario si quiere ver la respuesta. Nuevamente, cumplimos con las recomendaciones para menús contextuales de las directrices para información visual y el lenguaje táctil de Windows 8.

    Nota  Para concentrar la atención sobre el código de control de gestos, no se implementan completamente ciertas funciones de la aplicación y la interfaz de usuario ni la lectura de datos de preguntas y respuestas de un archivo XML.

Este es el HTML para este ejemplo.


<html>
<head>
    <meta charset="utf-8" />
    <title>js</title>

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

    <!-- BasicGesture references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <div class="TargetContainer" id="targetContainer">
        <div id="inputBox">
            <div id="instructions">Tap gray box below: Double tap to start questions, tap for next question, press and hold to show clues.</div>
            <div id="questions">&nbsp;</div>
            <div id="answers">
                <label for="answer">Answer:</label>
                <input type="text" id="answer" maxlength="30" size="30" style="z-index:1" />
                <button id="submit">Submit</button>
                <button id="stumped">Stumped</button>                
            </div>
            <div id="clues">

            </div>
            <div id="timerBox"></div>
        </div>
        <div id="eventLog"></div>

        <div id="answerFloater">
            <p>Show answer?</p>
            <button id="yes">Yes</button>
            <button id="no">No</button>
        </div>
    </div>
</body>
</html>


Esta es la hoja de estilo en cascada (CSS) para este ejemplo.

Nota  Los eventos de puntero no se desencadenan durante una interacción de zoom o desplazamiento lateral. Puedes deshabilitar el zoom y el desplazamiento lateral en una región mediante las propiedades msTouchAction, overflow y -ms-content-zooming de CSS.


body {
/*
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.
*/
    overflow: hidden;
    position: absolute;
    font-family: 'Segoe UI';
    font-size: small;
    -ms-touch-action: none;
    background-color: black;
}

div #targetContainer {
    position: relative;
    height: fill-available;
    width: fill-available;
}

div #inputBox {
    position: relative;
    width: 640px;
    height: 640px;
    color: black;
    overflow: hidden;
    background-color: darkgrey;
    margin: 0px;
    padding: 0px;
    border-width: 1px;
    border-color: white;
    border-style: solid;
}

div #instructions {
    position: relative;
    width: 100%;
    height: fit-content;
    color: black;
    background-color: white;
    visibility: visible;
}

div #questions {
    position: relative;
    width: 100%;
    height: fit-content;
    color: white;
    background-color: black;
    visibility: visible;
}

div #answers {
    position: relative;
    width: 100%;
    height: fit-content;
    color: white;
    background-color: black;
    visibility: visible;
}

div #clues {
    position: relative;
    width: 100%;
    height: 100%;
    background-color: DimGray;
}

div #timerBox {
    background-color: red;
    color: black;
    position: absolute;
    width: 100%;
    bottom: 0px;
    height: 20px;
    text-align: center;
}

div #answerFloater {
    position: absolute;
    visibility: hidden;
    top: 0px;
    left: 0px;
    background-color: blue;
}

div #eventLog {
    font-size: xx-small;
    position: absolute;
    left: 0px;
    top: 0px;
    width: 640px;
    height: 50px;
    overflow: auto;
    overflow-style: auto;
}


Inicializar la aplicación

Inicializa el objeto de preguntas y respuestas.

Aquí declaramos variables globales e inicializamos los objetos de la interfaz de usuario.


var _applicationData;
var _localSettings;
var _data;
var _inputBox;
var _instructions;
var _answers;
var _questions;
var _clues;
var _eventLog;
var _eventLog;
var _floater;


function initialize() {

    // Load xml data from file into local app settings.
    dataObject.initialize();
    _data = dataObject.getData();

    // Get our UI objects.
    _inputBox = document.getElementById("inputBox");
    _instructions = document.getElementById("instructions");
    _questions = document.getElementById("questions");
    _answers = document.getElementById("answers");
    _clues = document.getElementById("clues");
    _eventLog = document.getElementById("eventLog");
    _floater = document.getElementById("answerFloater");

    // Configure the target.
    setTarget();

}


Luego configuramos el objeto de interacción y leemos los datos de preguntas y respuestas del archivo XML en nuestro objeto de datos (dataObject). Los detalles de los datos XML para este ejemplo se pueden revisar en la lista completa al final de este tema.


// Configure the interaction target.
function setTarget() {
    //  Set the position of the input target.
    var inputLeft = (window.innerWidth - _inputBox.clientWidth) / 2.0;
    var inputTop = (window.innerHeight - _inputBox.clientHeight) / 2.0;
    var transform = (new MSCSSMatrix()).translate(inputLeft, inputTop);
    _inputBox.style.msTransform = transform;

    // Set the position of the event log.
    transform = (new MSCSSMatrix()).translate(inputLeft, inputTop + _inputBox.clientHeight);
    _eventLog.style.msTransform = transform;

    // Associate interaction target with our input manager.
    // Scope input to clue area only.
    _clues.inputManager = new inputManager(_clues);
}


Configurar el reconocedor de gestos

Configura el control de interacciones.

El reconocedor de gestos (inputManager) escucha y controla todos los eventos de gestos y de puntero.

Nota  En la mayoría de los casos, te recomendamos obtener información de puntero mediante los controladores de eventos de puntero de los marcos de lenguaje de Windows 8 que hayas elegido (aplicaciones de la Tienda Windows con JavaScript, aplicaciones de la Tienda Windows creadas para Windows con C++, C# o Visual Basic o aplicaciones de la Tienda Windows creadas para Windows mediante DirectX con C++). El PointerPoint asociado con el controlador de eventos ofrece información en el contexto del elemento de interfaz de usuario de destino, mientras que los métodos PointerPoint (GetCurrentPoint y GetIntermediatePoints) ofrecen información en el contexto de la pantalla o ventana principal.


// inputManager handles gesture recognition for this sample.
function inputManager(target) {
    var questionsStarted = false;
    var tapCount = 0;
    var questionTotal = _data.selectNodes("questions/question").length;
    var clueCount = 0;
    var doubleTap = false;
    var startTime;
    var clueTimer;
    var intervalTimerId;

    // Initialize the gesture recognizer.
    var gr = new Windows.UI.Input.GestureRecognizer();

    // Turn off visual feedback for gestures.
    // Visual feedback for pointer input is still displayed. 
    gr.showGestureFeedback = false;

    // Configure gesture recognizer to process the following:
    // double tap               - start questions and timer.
    // tap                      - move to next question.
    // right tap                - show answer.
    // hold and hold with mouse - start clues.
    gr.gestureSettings =
        Windows.UI.Input.GestureSettings.tap |
        Windows.UI.Input.GestureSettings.doubleTap |
        Windows.UI.Input.GestureSettings.rightTap |
        Windows.UI.Input.GestureSettings.hold |
        Windows.UI.Input.GestureSettings.holdWithMouse;

    // Register event listeners for these gestures.
    gr.addEventListener('tapped', tappedHandler);
    gr.addEventListener("holding", holdingHandler);
    gr.addEventListener("righttapped", rightTappedHandler);

    // Register event listeners for DOM pointer events.
    // The event pointer(s) are passed to the gesture recognizer
    // for further processing.
    target.addEventListener('MSPointerDown', pointerDown, false);
    target.addEventListener('MSPointerMove', pointerMove, false);
    target.addEventListener('MSPointerUp', pointerUp, false);
    target.addEventListener("MSPointerOver", pointerOver, true);
    target.addEventListener("MSPointerOut", pointerOut, true);

    // The following functions are registered to handle DOM pointer events

    // Basic pointer handling to highlight input area.
    function pointerOver(evt) {
        _eventLog.innerText += "pointer over || ";
        evt.target.style.backgroundColor = "DarkGray";
    }
    function pointerOut(evt) {
        _eventLog.innerText += "pointer out || ";
        evt.target.style.backgroundColor = "DimGray";
    }

    // Handle the pointer down event.
    function pointerDown(evt) {
        _eventLog.innerText += "pointer down || ";

        // Hide the floater if visible.
        _floater.style.visibility = "hidden";

        // Get the PointerPoint for the pointer event.
        var pp = evt.currentPoint;

        // Get whether this pointer down event is within
        // the time threshold for a double tap.
        doubleTap = gr.canBeDoubleTap(pp);

        // Pass the PointerPoint to the gesture recognizer.
        gr.processDownEvent(pp);
    };

    // Handle the pointer move event.
    // The holding gesture is routed through this event.
    // If pointer move is not handled, holding will not fire.
    function pointerMove(evt) {
        //_eventLog.innerText += "pointer move || ";

        // Get intermediate PointerPoints
        var pps = evt.intermediatePoints;

        // Pass the array of PointerPoints to the gesture recognizer.
        gr.processMoveEvents(pps);
    };

    // Handle the pointer up event.
    function pointerUp(evt) {
        _eventLog.innerText += "pointer up || ";

        // Get the current PointerPoint
        var pp = evt.currentPoint;

        // Pass the PointerPoint to the gesture recognizer.
        gr.processUpEvent(pp);
    };

    // The following functions are registered to handle gesture events.

    // This handler processes taps and double taps.
    // Potential double taps are identified in the pointer down handler.
    function tappedHandler(evt) {
        // Single tap and questions started: Display next question.
        if (!doubleTap && questionsStarted) {
            _eventLog.innerText += "tapped || ";
            _instructions.innerText = "Double tap to stop questions.";
            _clues.innerText = "";
            tapCount++;
            if (tapCount > questionTotal) {
                _questions.innerText = "No more questions.";
            } else {
                var xpath = "questions/question[" + (tapCount % (questionTotal + 1)) + "]/q";
                // Read data from a simple setting
                _questions.innerText = _data.selectSingleNode(xpath).innerText;
            }
        }
        // Single tap and questions not started: Don't do much.
        else if (!doubleTap && !questionsStarted) {
            _eventLog.innerText += "tapped || ";
            _instructions.innerText = "Double tap to start questions.";
        }
        // Double tap and questions not started: Display first question.
        else if (doubleTap && !questionsStarted) {
            _eventLog.innerText += "double-tapped || ";
            // Return if last question displayed.
            if (tapCount > questionTotal) {
                _questions.innerText = "No more questions.";
                return;
            }
            // Start questions.
            questionsStarted = true;
            _instructions.innerText = "Starting questions (double tap to stop questions).";

            // Question number is based on tap count.
            tapCount++;

            // Select question from XML data object.
            var xpath = "questions/question[" + (tapCount % (questionTotal + 1)) + "]/q";
            _questions.innerText = _data.selectSingleNode(xpath).innerText;

            // Display a basic timer once questions started.
            startTime = new Date().getTime();
            intervalTimerId = setInterval(displayTimer, 100);
        }
        // Double tap and questions started: Stop questions and timer.
        else if (doubleTap && questionsStarted) {
            _eventLog.innerText += "double-tapped || ";
            _instructions.innerText = "Questions stopped (double tap to start questions).";
            questionsStarted = false;
            clearInterval(intervalTimerId);
        }
    };

    // For this app, we display a basic timer once questions start.
    // In a more robust app, could be used for achievements.
    function displayTimer() {
        var x = new Date().getTime();
        timerBox.innerText = (x - startTime) / 1000;
    }

    // This handler processes right taps.
    // For all pointer devices a right tap is fired on
    // the release of a press and hold gesture.
    // For mouse devices, righttapped is also fired on a right button click.
    // For pen devices, 
    function rightTappedHandler(evt) {
        if (!questionsStarted) {
            return;
        }
        var transform = (new MSCSSMatrix()).
            translate(
            (window.innerWidth - _inputBox.clientWidth) / 2.0 + evt.position.x,
            (window.innerHeight - _inputBox.clientHeight) / 2.0 + evt.position.y);
        _floater.style.visibility = "visible";
        _floater.style.msTransform = transform;
        eventLog.innerText = "right-tap || ";
    }

    // A holding event is fired approximately one second after 
    // a pointer down if no subsequent movement is detected.
    // Handle the pointer move event.
    // The holding gesture is routed through this event.
    // If pointer move is not handled, holding will not fire.
    function holdingHandler(evt) {
        if (!questionsStarted)
            return;
        if (evt.holdingState == Windows.UI.Input.HoldingState.started) {
            _eventLog.innerText += "holding || ";
            clueManager.initialize(tapCount);
        } else if (evt.holdingState == Windows.UI.Input.HoldingState.completed) {
            clueManager.destroy();
            _eventLog.innerText += "holding completed || ";
        } else {
            _eventLog.innerText += "holding canceled || ";
        }
    }

};


Finalmente, configuramos el administrador de pistas que muestra una serie de pistas para la pregunta actual durante el gesto de pulsar y sostener.


var clueManager = (function () {
    var that = {};
    var clueTimerId;

    that.initialize = function (tapCount) {
        var clue;
        var clueCount = 0;
        var clueCollection = _data.selectNodes("questions/question[" + tapCount + "]/clues/clue");

        clueTimerId = setInterval(function () {
            clueCount++;

            if (clueCount > clueCollection.length) {
                _clues.innerText += "\nNo more clues.";
                clearInterval(clueTimerId);
                return;
            }

            if (clueCount == 1)
                clue = clueCollection.first();

            _clues.innerText += "\n" + clue.current.innerText;
            clue.moveNext();
        }, 2000);
    }

    that.destroy = function () {
        clearInterval(clueTimerId);
    }
    return that;
})();


Ejemplo completo

A continuación se encuentra el código de JavaScript para este ejemplo. Consulta Temas relacionados en la parte inferior de esta página para obtener vínculos a muestras más complejas.


"use strict";
var _applicationData;
var _localSettings;
var _data;
var _inputBox;
var _instructions;
var _answers;
var _questions;
var _clues;
var _eventLog;
var _eventLog;
var _floater;


function initialize() {

    // Load xml data from file into local app settings.
    dataObject.initialize();
    _data = dataObject.getData();

    // Get our UI objects.
    _inputBox = document.getElementById("inputBox");
    _instructions = document.getElementById("instructions");
    _questions = document.getElementById("questions");
    _answers = document.getElementById("answers");
    _clues = document.getElementById("clues");
    _eventLog = document.getElementById("eventLog");
    _floater = document.getElementById("answerFloater");

    // Configure the target.
    setTarget();

}

// Configure the interaction target.
function setTarget() {
    //  Set the position of the input target.
    var inputLeft = (window.innerWidth - _inputBox.clientWidth) / 2.0;
    var inputTop = (window.innerHeight - _inputBox.clientHeight) / 2.0;
    var transform = (new MSCSSMatrix()).translate(inputLeft, inputTop);
    _inputBox.style.msTransform = transform;

    // Set the position of the event log.
    transform = (new MSCSSMatrix()).translate(inputLeft, inputTop + _inputBox.clientHeight);
    _eventLog.style.msTransform = transform;

    // Associate interaction target with our input manager.
    // Scope input to clue area only.
    _clues.inputManager = new inputManager(_clues);
}


// inputManager handles gesture recognition for this sample.
function inputManager(target) {
    var questionsStarted = false;
    var tapCount = 0;
    var questionTotal = _data.selectNodes("questions/question").length;
    var clueCount = 0;
    var doubleTap = false;
    var startTime;
    var clueTimer;
    var intervalTimerId;

    // Initialize the gesture recognizer.
    var gr = new Windows.UI.Input.GestureRecognizer();

    // Turn off visual feedback for gestures.
    // Visual feedback for pointer input is still displayed. 
    gr.showGestureFeedback = false;

    // Configure gesture recognizer to process the following:
    // double tap               - start questions and timer.
    // tap                      - move to next question.
    // right tap                - show answer.
    // hold and hold with mouse - start clues.
    gr.gestureSettings =
        Windows.UI.Input.GestureSettings.tap |
        Windows.UI.Input.GestureSettings.doubleTap |
        Windows.UI.Input.GestureSettings.rightTap |
        Windows.UI.Input.GestureSettings.hold |
        Windows.UI.Input.GestureSettings.holdWithMouse;

    // Register event listeners for these gestures.
    gr.addEventListener('tapped', tappedHandler);
    gr.addEventListener("holding", holdingHandler);
    gr.addEventListener("righttapped", rightTappedHandler);

    // Register event listeners for DOM pointer events.
    // The event pointer(s) are passed to the gesture recognizer
    // for further processing.
    target.addEventListener('MSPointerDown', pointerDown, false);
    target.addEventListener('MSPointerMove', pointerMove, false);
    target.addEventListener('MSPointerUp', pointerUp, false);
    target.addEventListener("MSPointerOver", pointerOver, true);
    target.addEventListener("MSPointerOut", pointerOut, true);

    // The following functions are registered to handle DOM pointer events

    // Basic pointer handling to highlight input area.
    function pointerOver(evt) {
        _eventLog.innerText += "pointer over || ";
        evt.target.style.backgroundColor = "DarkGray";
    }
    function pointerOut(evt) {
        _eventLog.innerText += "pointer out || ";
        evt.target.style.backgroundColor = "DimGray";
    }

    // Handle the pointer down event.
    function pointerDown(evt) {
        _eventLog.innerText += "pointer down || ";

        // Hide the floater if visible.
        _floater.style.visibility = "hidden";

        // Get the PointerPoint for the pointer event.
        var pp = evt.currentPoint;

        // Get whether this pointer down event is within
        // the time threshold for a double tap.
        doubleTap = gr.canBeDoubleTap(pp);

        // Pass the PointerPoint to the gesture recognizer.
        gr.processDownEvent(pp);
    };

    // Handle the pointer move event.
    // The holding gesture is routed through this event.
    // If pointer move is not handled, holding will not fire.
    function pointerMove(evt) {
        //_eventLog.innerText += "pointer move || ";

        // Get intermediate PointerPoints
        var pps = evt.intermediatePoints;

        // Pass the array of PointerPoints to the gesture recognizer.
        gr.processMoveEvents(pps);
    };

    // Handle the pointer up event.
    function pointerUp(evt) {
        _eventLog.innerText += "pointer up || ";

        // Get the current PointerPoint
        var pp = evt.currentPoint;

        // Pass the PointerPoint to the gesture recognizer.
        gr.processUpEvent(pp);
    };

    // The following functions are registered to handle gesture events.

    // This handler processes taps and double taps.
    // Potential double taps are identified in the pointer down handler.
    function tappedHandler(evt) {
        // Single tap and questions started: Display next question.
        if (!doubleTap && questionsStarted) {
            _eventLog.innerText += "tapped || ";
            _instructions.innerText = "Double tap to stop questions.";
            _clues.innerText = "";
            tapCount++;
            if (tapCount > questionTotal) {
                _questions.innerText = "No more questions.";
            } else {
                var xpath = "questions/question[" + (tapCount % (questionTotal + 1)) + "]/q";
                // Read data from a simple setting
                _questions.innerText = _data.selectSingleNode(xpath).innerText;
            }
        }
        // Single tap and questions not started: Don't do much.
        else if (!doubleTap && !questionsStarted) {
            _eventLog.innerText += "tapped || ";
            _instructions.innerText = "Double tap to start questions.";
        }
        // Double tap and questions not started: Display first question.
        else if (doubleTap && !questionsStarted) {
            _eventLog.innerText += "double-tapped || ";
            // Return if last question displayed.
            if (tapCount > questionTotal) {
                _questions.innerText = "No more questions.";
                return;
            }
            // Start questions.
            questionsStarted = true;
            _instructions.innerText = "Starting questions (double tap to stop questions).";

            // Question number is based on tap count.
            tapCount++;

            // Select question from XML data object.
            var xpath = "questions/question[" + (tapCount % (questionTotal + 1)) + "]/q";
            _questions.innerText = _data.selectSingleNode(xpath).innerText;

            // Display a basic timer once questions started.
            startTime = new Date().getTime();
            intervalTimerId = setInterval(displayTimer, 100);
        }
        // Double tap and questions started: Stop questions and timer.
        else if (doubleTap && questionsStarted) {
            _eventLog.innerText += "double-tapped || ";
            _instructions.innerText = "Questions stopped (double tap to start questions).";
            questionsStarted = false;
            clearInterval(intervalTimerId);
        }
    };

    // For this app, we display a basic timer once questions start.
    // In a more robust app, could be used for achievements.
    function displayTimer() {
        var x = new Date().getTime();
        timerBox.innerText = (x - startTime) / 1000;
    }

    // This handler processes right taps.
    // For all pointer devices a right tap is fired on
    // the release of a press and hold gesture.
    // For mouse devices, righttapped is also fired on a right button click.
    // For pen devices, 
    function rightTappedHandler(evt) {
        if (!questionsStarted) {
            return;
        }
        var transform = (new MSCSSMatrix()).
            translate(
            (window.innerWidth - _inputBox.clientWidth) / 2.0 + evt.position.x,
            (window.innerHeight - _inputBox.clientHeight) / 2.0 + evt.position.y);
        _floater.style.visibility = "visible";
        _floater.style.msTransform = transform;
        eventLog.innerText = "right-tap || ";
    }

    // A holding event is fired approximately one second after 
    // a pointer down if no subsequent movement is detected.
    // Handle the pointer move event.
    // The holding gesture is routed through this event.
    // If pointer move is not handled, holding will not fire.
    function holdingHandler(evt) {
        if (!questionsStarted)
            return;
        if (evt.holdingState == Windows.UI.Input.HoldingState.started) {
            _eventLog.innerText += "holding || ";
            clueManager.initialize(tapCount);
        } else if (evt.holdingState == Windows.UI.Input.HoldingState.completed) {
            clueManager.destroy();
            _eventLog.innerText += "holding completed || ";
        } else {
            _eventLog.innerText += "holding canceled || ";
        }
    }

};

var clueManager = (function () {
    var that = {};
    var clueTimerId;

    that.initialize = function (tapCount) {
        var clue;
        var clueCount = 0;
        var clueCollection = _data.selectNodes("questions/question[" + tapCount + "]/clues/clue");

        clueTimerId = setInterval(function () {
            clueCount++;

            if (clueCount > clueCollection.length) {
                _clues.innerText += "\nNo more clues.";
                clearInterval(clueTimerId);
                return;
            }

            if (clueCount == 1)
                clue = clueCollection.first();

            _clues.innerText += "\n" + clue.current.innerText;
            clue.moveNext();
        }, 2000);
    }

    that.destroy = function () {
        clearInterval(clueTimerId);
    }
    return that;
})();

var dataObject = (function () {
    var that = {};
    var applicationData = Windows.Storage.ApplicationData.current;
    var localSettings = applicationData.localSettings;
    that.initialize = function () {
        // This sample uses data/data.xml (Assume valid, set file properties: Package Action - Content / Copy to Output Directory - Always)
        // Use default load settings.
        Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("data").then(function (dataFolder) {
            dataFolder.getFileAsync("data.xml").then(function (dataFile) {
                Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(dataFile).then(function (data) {
                    // Create a simple setting
                    try {
                        localSettings.values["data"] = data.getXml();
                    } catch (e) {
                        _eventLog.innerText += e.description;
                    }

                }, function (error) {
                    _eventLog.innerText += "Error: Unable to load XML file";
                });
            }, function (error) {
                _eventLog.innerText += error.description;
            });
        }, function (error) {
            _eventLog.innerText += error.description;
        });
    };
    that.getData = function () {
        var data = new Windows.Data.Xml.Dom.XmlDocument;

        var xmlLoadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings();
        xmlLoadSettings.elementContentWhiteSpace = false;
        data.loadXml(localSettings.values["data"], xmlLoadSettings);
        return data;
    }
    return that;
})();

function loadData() {
    // This sample uses data/data.xml (Assume valid, set file properties: Package Action - Content / Copy to Output Directory - Always)
    // Use default load settings.
    _applicationData = Windows.Storage.ApplicationData.current;
    _localSettings = _applicationData.localSettings;
    Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("data").then(function (dataFolder) {
        dataFolder.getFileAsync("data.xml").then(function (dataFile) {
            Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(dataFile).then(function (data) {
                // Create a simple setting
                try {
                    _localSettings.values["data"] = data.getXml();
                } catch (e) {
                    _eventLog.innerText += e.description;
                }

            }, function (error) {
                _eventLog.innerText += "Error: Unable to load XML file";
            });
        }, function (error) {
            _eventLog.innerText += error.description;
        });
    }, function (error) {
        _eventLog.innerText += error.description;
    });
};

(function () {
    document.addEventListener("DOMContentLoaded", initialize, false);
})();


Resumen y next steps

En este inicio rápido has aprendido a controlar los eventos de gesto estático en aplicaciones de la Tienda Windows con JavaScript.

El reconocimiento de gestos básicos, junto con los eventos de puntero, es útil para administrar interacciones simples, como pulsación, doble pulsación, pulsar y sostener, y pulsación derecha.

Consulta el tema sobre entrada: muestra de gestos instanciables para ver un ejemplo más complejo del control de gestos.

Nota  Esta muestra no cumple con las directrices del lenguaje táctil de Windows 8 en cuanto a las interacciones personalizadas. Algunos de los gestos estáticos se han redefinido para fines instructivos.

Consulta Inicio rápido: gestos de manipulación para controlar interacciones de manipulación más elaboradas (como deslizar, deslizar rápidamente, girar, reducir y ampliar) con el fin de proporcionar una experiencia de interacción de usuario totalmente personalizada.

Para más información sobre el lenguaje táctil de Windows 8, consulta el tema sobre el diseño de la interacción táctil.

Temas relacionados

Conceptual (JavaScript y HTML)
Responder a la interacción del usuario
Inicio rápido: punteros
Inicio rápido: gestos y manipulaciones de DOM
Inicio rápido: gestos de manipulación
Diseño de la interacción táctil
Muestras
Entrada: muestra de funcionalidades del dispositivo
Entrada: muestra de control de eventos de puntero y de gestos de DOM
Entrada: muestra de manipulaciones y gestos (JavaScript)
Entrada: muestra de gestos instanciables
Entrada: muestra de desplazamiento, desplazamiento lateral y zoom
Entrada: muestra de entrada de lápiz simplificada

 

 

Mostrar:
© 2018 Microsoft