Démarrage rapide : actions statiques (HTML)

[ Cet article est destiné aux développeurs de Windows 8.x et Windows Phone 8.x qui créent des applications Windows Runtime. Si vous développez une application pour Windows 10, voir la Documentation ]

Gérez les événements de mouvement Windows Runtime de base et personnalisez l’expérience utilisateur pour les actions statiques décrites dans le langage tactile de Windows (tels que l’appui, le double appui, l’appui prolongé et l’appui droit).

La plupart des applications traitent les mouvements (appuis, panoramiques, zooms, etc.) et gèrent peu les données de pointeur brutes à part pour les transmettre à la détection des mouvements. Dans cet exemple, nous utilisons ces données de pointeur brutes pour prendre en charge la gestion et le traitement des actions statiques pour développer le modèle d’interaction de votre application et pour s’appuyer sur les événements de pointeur de base décrits dans Démarrage rapide : pointeurs.

Mises à jour pour Windows 8.1: Dans Windows 8.1, les API d’entrée de pointeur ont fait l’objet de plusieurs mises à jour et améliorations. Pour plus d’informations, voir Modifications apportées aux API pour Windows 8.1.

Si vous débutez dans le développement d’applications en JavaScript: Examinez ces rubriques pour vous familiariser avec les technologies discutées ici.

Créer votre première application en JavaScript

Feuille de route pour les applications en JavaScript

Découvrir les événements avec Démarrage rapide : ajout de contrôles HTML et gestion des événements

Fonctionnalités d’application de A à Z:

Étudier cette fonctionnalité de façon plus approfondie dans le cadre de notre série Fonctionnalités d’application de A à Z

Interaction utilisateur de A à Z (HTML)

Personnalisation de l’interaction utilisateur de A à Z (HTML)

Recommandations en matière d’expérience utilisateur:

Les bibliothèques de contrôles de plateforme (HTML et XAML) fournissent une expérience d’interaction utilisateur complète, y compris les interactions standard, les effets physiques animés et le retour visuel. Utilisez ces contrôles intégrés si vous n’avez pas besoin d’une prise en charge d’interaction personnalisée.

Si les contrôles de plateforme ne suffisent pas, les présentes recommandations peuvent vous aider à fournir une expérience d’interaction utilisateur à la fois immersive et cohérente entre les divers modes d’entrée. Ces recommandations sont axées principalement sur l’entrée tactile, mais elles s’appliquent également à l’entrée de pavé tactile, de souris, de clavier et de stylet.

Exemples: Découvrez cette fonctionnalité en action dans nos exemples d’applications.

Exemple de personnalisation de l’interaction utilisateur de A à Z

Entrée : exemple de gestion d’événement de pointeur DOM

Entrée : exemple de manipulations et de mouvements (JavaScript)

Entrée : exemple de mouvements Windows 8

Objectif: apprendre à écouter, gérer et traiter les actions statiques à l’aide des entrées provenant d’interactions tactiles, avec la souris ou le stylo/stylet, ainsi que des événements de mouvement Windows Runtime.

Prérequis

Passez en revue Démarrage rapide : pointeurs et Démarrage rapide : manipulations et mouvements DOM.

Nous partons du principe que vous savez créer une application élémentaire en JavaScript qui utilise le modèle Bibliothèque Windows pour JavaScript.

Pour suivre ce didacticiel, vous devez :

Durée de réalisation: 30 minutes.

Qu’est-ce qu’un événement de mouvement ?

Un mouvement est l’acte physique ou le déplacement effectué sur ou par le périphérique d’entrée (un ou plusieurs doigts sur une surface tactile, un digitaliseur à stylo/stylet, une souris, etc.). Ces interactions naturelles sont mises en correspondance avec des éléments à la fois dans le système et dans votre application. Pour plus d’informations, voir Mouvements, manipulations et interactions.

Le tableau ci-dessous identifie les actions statiques traitées dans cette rubrique de démarrage rapide.

MouvementDescription
Appui / double appuiAction d’appuyer

Un contact unique qui est relâché ou arrêté immédiatement.

Le fait d’appuyer sur un élément appelle l’action primaire associée.

Un double appui correspond à deux appuis qui se suivent rapidement et peut être géré comme votre application le requiert.

  • État d’entrée : contact détecté dans le rectangle englobant d’un objet.
  • Capteur de mouvement : Aucun.
  • État de sortie : contact relâché ou arrêté.
Appui prolongé / appui droitAppui prolongé

Un contact unique persistant jusqu’à ce qu’un délai soit dépassé.

L’appui prolongé affiche des informations détaillées ou des éléments visuels didactiques (par exemple, une info-bulle ou un menu contextuel) ne requérant aucune action.

L’appui droit est étroitement associé au mouvement d’appui prolongé. L’événement d’appui droit est déclenché lors du relâchement de l’appui prolongé.

  • État d’entrée : contact détecté dans le rectangle englobant d’un objet.
  • Capteur de mouvement : Aucun.
  • État de sortie : contact relâché ou arrêté.

Pour plus d’informations sur ces mouvements et leur association au langage tactile de Windows, voir Conception de l’interaction tactile.

 

Important  Si vous implémentez votre propre prise en charge d’interaction, gardez à l’esprit que les utilisateurs s’attendent à disposer d’une expérience intuitive impliquant une interaction directe avec les éléments d’interface utilisateur de votre application. Nous vous recommandons de modeler vos interactions personnalisées sur les bibliothèques de contrôles de plateforme (HTML et XAML) pour des raisons de cohérence et de simplicité de détection. Les contrôles de ces bibliothèques fournissent une expérience d’interaction utilisateur complète, notamment pour les interactions standard, les effets physiques animés, le retour visuel et l’accessibilité. Ne créez des interactions personnalisées que pour répondre à des exigences claires et bien définies, notamment en l’absence d’interactions de base prenant en charge votre scénario.

 

Création de l’interface utilisateur

Cet exemple correspond à une application de type questions/réponses de base. Un carré (inputBox) fait office d’objet cible pour la détection et le traitement de l’entrée du pointeur et des actions statiques. Les questions, les indices et les réponses sont tous affichés au sein de cet objet.

L’application fournit les fonctionnalités d’interaction utilisateur suivantes :

  • Double appui : démarre et arrête les questions et le minuteur de l’application.
  • Appui : fait défiler les questions.
  • Appui prolongé : affiche un ensemble d’indices pour la question en cours, chaque nouvel indice étant affiché après un intervalle de quelques secondes alors que le contact reste appuyé. Ce comportement d’interaction est conforme aux recommandations en matière de retour visuel et aux recommandations relatives au langage tactile, qui stipulent que l’appui prolongé doit être limité à l’affichage de l’interface utilisateur informative.
  • Appui droit (ou relâchement de l’appui prolongé) : affiche une fenêtre contextuelle quand le contact est relâché, qui demande à l’utilisateur s’il souhaite la réponse. Là encore, nous respectons les recommandations en matière de menu contextuel stipulées dans les Recommandations en matière de retour visuel et le langage tactile de Windows. Remarque  Pour continuer à s’intéresser au code de gestion des mouvements, la lecture des données des questions et réponses à partir d’un fichier XML et certaines fonctionnalités d’interface utilisateur et de l’application ne sont pas entièrement implémentées.  

Voici le code HTML correspondant à cet exemple.

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

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <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/default.js"></script>
    <script src="/js/inputprocessor.js"></script>
    <script src="/js/datamanager.js"></script>
    <script src="/js/cluemanager.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>

Voici le code CSS (feuilles de style en cascade) correspondant à cet exemple.

Remarque  Les événements de pointeur ne se déclenchent pas au cours d’une interaction de panoramique ou de zoom. Vous pouvez désactiver les mouvements de panoramique et de zoom au niveau d’une région via les propriétés CSS msTouchAction, overflow et -ms-content-zooming.

 

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

Initialiser l’application

Initialisez l’objet des questions et réponses.

Ici, nous déclarons des variables globales et obtenons des références aux objets de l’interface utilisateur.

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

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

Nous positionnons ensuite l’interface utilisateur de question et réponse et nous définissons l’objet d’interaction pour traiter les données de question et réponse à partir du fichier XML. Les détails des données XML relatives à cet exemple peuvent être passés en revue dans la liste complète à la fin de cette rubrique.

// 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.inputProcessor = new QandA.InputProcessor(_clues);
}

Configurer la reconnaissance de mouvement

Configurez ici la gestion des interactions.

Dans la plupart des cas, nous vous conseillons d’obtenir les informations sur le pointeur via l’argument d’événement des gestionnaires d’événements de pointeur dans l’infrastructure de langage choisie.

Si l’argument d’événement n’expose pas les détails du pointeur nécessaires à votre application, vous pouvez obtenir l’accès aux données étendues du pointeur à partir de l’argument d’événement via les méthodes getCurrentPoint et getIntermediatePoints ou les propriétés currentPoint et intermediatePoints. Nous vous recommandons d’utiliser les méthodes getCurrentPoint et getIntermediatePoints car vous pouvez spécifier le contexte des données du pointeur.

Astuce  Pour cet exemple, un seul objet est associé à une reconnaissance de mouvement. Si votre application contient un grand nombre d’objets qui peuvent être manipulés (tels que des puzzles), envisagez de créer dynamiquement la reconnaissance de mouvement uniquement lorsque l’entrée du pointeur est détectée sur un objet cible. La reconnaissance de mouvement peut être détruite lorsque la manipulation est terminée (voir Entrée : exemple de mouvements instanciables). Pour éviter la surcharge de création et de destruction de reconnaissances de mouvement, créez un petit pool de reconnaissances de mouvement lors de l’initialisation et assignez-les dynamiquement au fil des besoins.

 

L’objet processeur d’entrée comprend la reconnaissance de mouvement (gr) qui écoute et traite tous les événements de pointeur et de mouvement. L’interface utilisateur de question et réponse est gérée par les gestionnaires d’événements de reconnaissance de mouvement.

// Handle gesture recognition for this sample.
(function () {
    "use strict";
    var InputProcessor = WinJS.Class.define(
    // Constructor
    function InputProcessor_ctor(target) {
        this._questionsStarted = false;
        this._tapCount = 0;
        // Create a clue manager.
        this._clueManager = new QandA.ClueManager();
        // Load xml data from file into local app settings.
        var _dataObject = new QandA.DataManager();
        _data = _dataObject.getData();

        this._questionTotal = _data.selectNodes("questions/question").length;
        this._doubleTap = false;
        this._startTime;
        this._intervalTimerId;

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

        // Turn off visual feedback for gestures.
        // Visual feedback for pointer input is still displayed. 
        this.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.
        this.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;

        //
        // Set event listeners.
        //
        // Get our context.
        var that = this;

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

        // The following functions are registered to handle DOM pointer events
        //
        // Basic pointer handling to highlight input area.
        target.addEventListener("pointerover", function onPointerOver(eventInfo) {
            eventInfo.stopImmediatePropagation = true;
            _eventLog.innerText += "pointer over || ";
            eventInfo.target.style.backgroundColor = "DarkGray";
        }, false);
        // Basic pointer handling to highlight input area.
        target.addEventListener("pointerout", function onPointerOut(eventInfo) {
            eventInfo.stopImmediatePropagation = true;
            _eventLog.innerText += "pointer out || ";
            eventInfo.target.style.backgroundColor = "DimGray";
        }, false);
        // Handle the pointer move event.
        // The holding gesture is routed through this event.
        // If pointer move is not handled, holding will not fire.
        target.addEventListener("pointermove", function onPointerMove(eventInfo) {
            eventInfo.stopImmediatePropagation = true;
            // Get intermediate PointerPoints
            var pps = eventInfo.intermediatePoints;

            // Pass the array of PointerPoints to the gesture recognizer.
            that.gr.processMoveEvents(pps);
        }, false);
        // Handle the pointer down event.
        target.addEventListener("pointerdown", function onPointerDown(eventInfo) {
            eventInfo.stopImmediatePropagation = true;
            _eventLog.innerText += "pointer down || ";

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

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

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

            // Pass the PointerPoint to the gesture recognizer.
            that.gr.processDownEvent(pp);
        }, false);
        // Handle the pointer up event.
        target.addEventListener("pointerup", function onPointerUp(eventInfo) {
            eventInfo.stopImmediatePropagation = true;
            _eventLog.innerText += "pointer up || ";

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

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

        // 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 (!that._doubleTap && that._questionsStarted) {
                _eventLog.innerText += "tapped || ";
                _instructions.innerText = "Double tap to stop questions.";
                _clues.innerText = "";
                that._tapCount++;
                that._clueManager.tapCount = that.tapCount;
                if (that._tapCount > that._questionTotal) {
                    _questions.innerText = "No more questions.";
                } else {
                    var xpath = "questions/question[" + (that._tapCount % (that._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 (!that._doubleTap && !that._questionsStarted) {
                _eventLog.innerText += "tapped || ";
                _instructions.innerText = "Double tap to start questions.";
            }
                // Double tap and questions not started: Display first question.
            else if (that._doubleTap && !that._questionsStarted) {
                _eventLog.innerText += "double-tapped || ";
                // Return if last question displayed.
                if (that._tapCount > that._questionTotal) {
                    _questions.innerText = "No more questions.";
                    return;
                }
                // Start questions.
                that._questionsStarted = true;
                _instructions.innerText = "Starting questions (double tap to stop questions).";

                // Question number is based on tap count.
                that._tapCount++;

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

                // Display a basic timer once questions started.
                that._startTime = new Date().getTime();
                that._intervalTimerId = setInterval(displayTimer, 100);
            }
                // Double tap and questions started: Stop questions and timer.
            else if (that._doubleTap && that._questionsStarted) {
                _eventLog.innerText += "double-tapped || ";
                _instructions.innerText = "Questions stopped (double tap to start questions).";
                that._questionsStarted = false;
                clearInterval(that._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 - that._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 (!that._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 || ";
        }

        // The pointer move event must also be handled because the 
        // holding gesture is routed through this event.
        // If pointer move is not handled, holding will not fire.
        // A holding event is fired approximately one second after 
        // a pointer down if no subsequent movement is detected.
        function holdingHandler(evt) {
            if (!that._questionsStarted)
                return;
            if (evt.holdingState == Windows.UI.Input.HoldingState.started) {
                _eventLog.innerText += "holding || ";
                // Create a clue manager.
                that._clueManager.tapCount = that._tapCount;
                // Start displaying clues.
                that._clueManager.displayClues();
            } else if (evt.holdingState == Windows.UI.Input.HoldingState.completed) {
                that._clueManager.destroy();
                _eventLog.innerText += "holding completed || ";
            } else {
                _eventLog.innerText += "holding canceled || ";
            }
        }
    },
    {},
    {});

    WinJS.Namespace.define("QandA", {
        InputProcessor: InputProcessor
    });
})();

Enfin, nous configurons le gestionnaire d’indices qui affiche une série d’indices en fonction de la question actuelle au cours d’un appui prolongé.

// Handle data for this sample.
(function () {
    "use strict";
    var ClueManager = WinJS.Class.define(
    // Constructor
    function ClueManager_ctor() {
        this._clueTimerId = null;
    },
    {
        displayClues: function () {
            var clue;
            var clueCount = 0;
            var clueCollection = _data.selectNodes("questions/question[" + this.tapCount + "]/clues/clue");

            this._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);
        },
        destroy: function () {
            clearInterval(this._clueTimerId);
        },
        tapCount: {
            get: function () {
                return this._tapCount;
            },
            set: function (tapCount) {
                this._tapCount = tapCount;
            }
        }
    },
    {});

    WinJS.Namespace.define("QandA", {
        ClueManager: ClueManager
    });
})();

Des liens vers des exemples plus complexes sont proposés à la section Rubriques associées, en bas de cette page.

Exemple complet

Voir Code complet des actions statiques.

Récapitulatif et étapes suivantes

Cette rubrique de démarrage rapide vous a appris à gérer les événements de mouvement statiques dans les applications du Windows Store en JavaScript.

La reconnaissance des mouvements de base, associée aux événements de pointeur, est utile dans le cadre de la gestion des interactions simples, telles que l’appui, le double appui, l’appui prolongé et l’appui droit.

Voir Entrée : exemple de mouvements instanciables pour consulter un exemple plus complexe de gestion des mouvements.

Remarque  Cet exemple n’est pas conforme aux recommandations du langage tactile de Windows concernant les interactions personnalisées. Certaines actions statiques ont été redéfinies à des fins didactiques.

 

Pour gérer des interactions de manipulation plus élaborées (telles que glissement, balayage, rotation, pincement et étirement ) pour fournir une expérience d’interaction utilisateur entièrement personnalisée, voir Démarrage rapide : actions de manipulation.

Pour plus d’informations sur le langage tactile de Windows, voir Conception de l’interaction tactile.

Rubriques associées

Développeurs

Réponse à l’interaction utilisateur

Développement d’applications du Windows Store (JavaScript et HTML)

Démarrage rapide : pointeurs

Démarrage rapide : manipulations et mouvements DOM

Démarrage rapide : actions de manipulation

Concepteurs

Conception de l’interaction tactile