Inicio rápido: punteros (HTML)

[ Este artículo está destinado a desarrolladores de Windows 8.x y Windows Phone 8.x que escriben aplicaciones de Windows en tiempo de ejecución. Si estás desarrollando para Windows 10, consulta la documentación más reciente

En las aplicaciones con JavaScript, las interacciones táctiles, del mouse y de lápiz o pluma se reciben, procesan y administran como entradas de puntero.

Actualizaciones para Windows 8.1: Windows 8.1 incorpora varias actualizaciones y mejoras para las API para entrada de puntero. Para obtener más información, consulta el tema sobre cambios en las API para Windows 8.1.

Si no estás familiarizado con el desarrollo de aplicaciones con JavaScript: Echa un vistazo a estos temas para familiarizarte con las tecnologías que se mencionan aquí.

Crear la primera aplicación de la Tienda Windows con JavaScript

Guía básica para crear aplicaciones de la Tienda Windows con JavaScript

Encontrarás más información sobre eventos en Inicio rápido: agregar controles HTML y controlar eventos

Funciones de la aplicación, de principio a fin:

Consulta esta funcionalidad con más detalle como parte de la serie Funciones de la aplicación, de principio a fin

Interacción del usuario, de principio a fin (HTML)

Personalización de la interacción del usuario, de principio a fin (HTML)

Directrices sobre la experiencia del usuario:

Las bibliotecas de control de la plataforma (HTML y XAML) proporcionan una experiencia de interacción del usuario de Windows completa, incluidas interacciones estándar, efectos físicos animados y comentarios visuales. Si no necesitas compatibilidad para interacción personalizada, usa estos controles integrados.

Si los controles de la plataforma no son suficientes, estas directrices para la interacción del usuario te pueden ayudar a proporcionar una experiencia de interacción atractiva y envolvente que sea coherente en todos los modos de entrada. Estas instrucciones se centran principalmente en la entrada táctil, pero también son válidas para entradas de panel táctil, mouse, teclado y lápiz.

Muestras: Puedes ver esta funcionalidad en acción en nuestras muestras de aplicaciones.

Personalización de la interacción del usuario, muestra de principio a fin

Muestra de desplazamiento, movimiento panorámico y zoom HTML

Entrada: muestra de control de eventos de puntero de DOM

Entrada: muestra de gestos instanciables

Entrada: muestra de entrada de lápiz

Entrada: muestra de manipulaciones y gestos (JavaScript)

Entrada: muestra de entrada de lápiz simplificada

Objetivo: Para obtener información sobre cómo escuchar y controlar la entrada de puntero.

Requisitos previos

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

Para completar este tutorial, necesitas:

Tiempo para finalizar: 30 minutos.

Instrucciones

¿Qué es una entrada de puntero?

Mediante la unificación de las entradas táctiles, de mouse y de lápiz o pluma en una entrada de puntero abstracta puedes controlar las interacciones del usuario con tu aplicación independientemente del tipo de dispositivo de entrada que se esté usando.

Un objeto de puntero representa un "contacto" de entrada único y singular (un PointerPoint) de un dispositivo de entrada (como mouse, pluma/lápiz, un dedo o varios dedos). El sistema crea un puntero cuando se detecta un contacto por primera vez, y se lo destruye cuando se cancela el puntero o este deja el intervalo de detección. En el caso de dispositivos múltiples o entrada multitoque, cada contacto se trata como un solo puntero.

Existe un amplio conjunto de API para entrada de puntero que pueden interceptar datos de entrada en forma directa a partir de diversos dispositivos. Puedes controlar los eventos de puntero para obtener información común, como el tipo de dispositivo o la ubicación, e información extendida, como la geometría de contacto y la presión. Como en muchos casos las aplicaciones deben responder a distintos modos de entrada de diferentes maneras, también se encuentran disponibles propiedades de dispositivo específicas, como qué botón del mouse presionó un usuario o si un usuario está usando el extremo borrador del lápiz. Por ejemplo, se puede filtrar la entrada táctil para que sea compatible con interacciones como movimiento panorámico y desplazamiento, mientras que el mouse y la pluma/lápiz suelen resultar más adecuados para tareas precisas como escribir con lápiz y dibujar. Si tu aplicación necesita diferenciar entre distintos dispositivos de entrada y sus funcionalidades, consulta el tema de inicio rápido: identificación de dispositivos de entrada.

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

Para este ejemplo, usamos un rectángulo (target) como el objeto de destino de la entrada de puntero. El color del destino cambia cuando cambia el estado del puntero.

Se muestran detalles de cada puntero en un bloque de texto flotante que se encuentra situado al lado del puntero y sigue cualquier movimiento de este. Los eventos de puntero específicos aparecen en el extremo derecho de la pantalla. La siguiente captura de pantalla muestra la interfaz de usuario para este ejemplo.

Captura de pantalla de la interfaz de usuario de la aplicación de ejemplo.

Este es el HTML para este ejemplo.

Nota  Aplicaciones de la Tienda Windows

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>PointerInput_Universal.Windows</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>

    <!-- PointerInput_Universal.Windows references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body class="windows">
    <div id="grid">
        <div id="targetContainer">
            <div id="target"></div>
        </div>
        <div id="bottom">
        </div>
        <div id="eventLog"></div>
    </div>
</body>
</html>

Nota  Aplicaciones de la Tienda de Windows Phone

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>PointerInput_Universal.WindowsPhone</title>

    <!-- WinJS references -->
    <!-- At runtime, ui-themed.css resolves to ui-themed.light.css or ui-themed.dark.css 
    based on the user’s theme setting. This is part of the MRT resource loading functionality. -->
    <link href="/css/ui-themed.css" rel="stylesheet" />
    <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
    <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>

    <!-- PointerInput_Universal.Phone references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body class="phone">
    <div id="grid">
        <div id="targetContainer">
            <div id="target"></div>
        </div>
        <div id="bottom">
        </div>
        <div id="eventLog"></div>
    </div>
</body>
</html>

Esta es la hoja de estilo 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 a través de las propiedades de CSS msTouchAction, overflow y -ms-content-zooming.

 

body {
    overflow: hidden;
    position: relative;
}

#grid {
    display: -ms-grid;
    height: 100vh; /* 100% of viewport height */
    -ms-grid-columns: 4fr 1fr; /* 2 columns */
    -ms-grid-rows: 1fr 320px 1fr;  /* 3 rows */
    /*touch-action: none;*/ /* Disable panning and zooming */
}
#targetContainer {
    border:solid;
    border-width:thin;
    border-color: red;
    -ms-grid-row: 2;
    -ms-grid-column: 1;
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
    /*touch-action: none; /* Disable panning and zooming */*/
}
#eventLog {
    -ms-grid-row: 1;
    -ms-grid-column: 2; 
    -ms-grid-row-span: 3;
    padding-right: 10px;
    background-color: black;
    color: white;
}
.phone #target {
    width: 200px;
    height: 300px;
    border: none;
    padding: 0px;
    margin: 0px;
    -ms-transform-origin: 0% 0%;
    /*touch-action: none; /* Disable panning and zooming */*/
}
.windows #target {
    width: 400px;
    height: 200px;
    border: none;
    padding: 0px;
    margin: 0px;
    -ms-transform-origin: 0% 0%;
    touch-action: none; /* Disable panning and zooming */
}

Escuchar eventos de puntero

En la mayoría de los casos, recomendamos que obtengas información de puntero mediante el argumento de evento de los controladores de eventos de puntero en el marco de trabajo de la lengua que has seleccionado.

Si el argumento de evento no expone los detalles de puntero que necesita tu aplicación, puedes acceder a los datos extendidos de puntero del argumento de evento con los métodos getCurrentPoint y getIntermediatePoints, o las propiedades currentPoint y intermediatePoints. Te recomendamos usar los métodos getCurrentPoint y getIntermediatePoints, que permiten especificar el contexto de los datos de puntero.

La siguiente captura de pantalla muestra el área de destino con detalles del puntero del mouse de este ejemplo.

Captura de pantalla del área de destino del puntero.

Aquí establecemos la ubicación de la pantalla y las escuchas de eventos del área de destino.

Primero, declaramos variables globales, inicializamos las áreas de detalles del puntero y el destino, e identificamos el registrador de eventos

// For this example, we track simultaneous contacts in case the 
// number of contacts has reached the maximum supported by the device.
// Depending on the device, additional contacts might be ignored 
// (PointerPressed not fired). 
var numActiveContacts = 0;

// The input target.
var target;

// Target background colors corresponding to various pointer states.
var pointerColor = {
    hover: "rgb(255, 255, 102)",
    down: "rgb(0, 255, 0)",
    up: "rgb(255, 0, 0)",
    cancel: "rgb(0,0,0)",
    out: "rgb(127,127,127)",
    over: "rgb(0,0,255)"
};

// The event log (updated on each event).
var eventLog;

function initialize() {
    /// <summary>Set up the app.</summary>
    eventLog = document.getElementById("eventLog");
    target = document.getElementById("target");
    setTarget();
}

Después, establecemos el objeto de destino y declaramos los diversos agentes de escucha de eventos de puntero para el destino.

function setTarget() {
    /// <summary>Set up the target and interaction event handlers.</summary>

    // Initial color of target.
    target.style.backgroundColor = pointerColor.out;

    // Expando dictionary property to track active contacts. 
    // An entry is added during pointer down/hover/over events 
    // and removed during pointer up/cancel/out/lostpointercapture events.
    target.pointers = [];

    // Declare pointer event handlers.
    target.addEventListener("pointerdown", onPointerDown, true);
    target.addEventListener("pointerover", onPointerOver, true);
    target.addEventListener("pointerup", onPointerUp, true);
    target.addEventListener("pointerout", onPointerOut, true);
    target.addEventListener("pointercancel", onPointerCancel, true);
    target.addEventListener("lostpointercapture", onLostPointerCapture, true);
    target.addEventListener("pointermove", onPointerMove, true);
    target.addEventListener("wheel", onMouseWheel, false);
}

Finalmente, establecemos el área de detalles del puntero.

function createInfoPop(e) {
    /// <summary>
    /// Create and insert DIV into the DOM for displaying pointer details.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>
    var infoPop = document.createElement("div");
    infoPop.setAttribute("id", "infoPop" + e.pointerId);

    // Set screen position of DIV.
    var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20);
    infoPop.style.msTransform = transform;
    target.appendChild(infoPop);

    infoPop.innerText = queryPointer(e);
}

function updateInfoPop(e) {
    /// <summary>
    /// Update pointer details in UI.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>
    var infoPop = document.getElementById("infoPop" + e.pointerId);
    if (infoPop === null)
        return;

    // Set screen position of DIV.
    var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20);
    infoPop.style.msTransform = transform;
    infoPop.innerText = queryPointer(e);
}

Controlar eventos de puntero

A continuación, usamos comentarios de interfaz de usuario para demostrar controladores de eventos de puntero básicos.

  • Este controlador administra un evento de contacto de puntero (hacia abajo, presionado). Agregamos el evento al registro de eventos, agregamos el puntero a la matriz de punteros usada para realizar un seguimiento de los punteros de interés y mostramos los detalles de los punteros.

    Nota  Los eventos pointerdown y pointerup no siempre se producen en pares. Tu aplicación debe escuchar y controlar cualquier evento que pueda dar conclusión a una acción de puntero abajo (como pointerup, pointerout, pointercancel y lostpointercapture).

     

    function onPointerDown(e) {
        /// <summary>
        /// Occurs for mouse when at least one mouse button is pressed or 
        /// for touch and pen when there is physical contact with the digitizer.
        /// For input devices that do not support hover, the pointerover event is 
        /// fired immediately before the pointerdown event.  
        /// Here, we  filter pointer input based on the first pointer type detected. 
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // pointerdown and pointerup events do not always occur in pairs. 
        // Listen for and handle any event that might conclude a pointer down action 
        // (such as pointerup, pointerout, pointercancel, and lostpointercapture).
        //
        // For this example, we track the number of contacts in case the 
        // number of contacts has reached the maximum supported by the device.
        // Depending on the device, additional contacts might be ignored 
        // (PointerPressed not fired). 
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Check if the number of supported contacts is exceeded.
        var touchCapabilities = new Windows.Devices.Input.TouchCapabilities();
        if ((touchCapabilities.touchPresent != 0) & (numActiveContacts > touchCapabilities.contacts)) {
            return;
        }
    
        // Update event details and target UI.
        eventLog.innerText += "\nDown: " + e.pointerId;
        target.style.backgroundColor = pointerColor.down;
    
        // Check if pointer already exists (if hover/over occurred prior to down).
        for (var i in target.pointers) {
            if (target.pointers[i].id = e.pointerId) {
                return;
            }
        }
    
        // Push new pointer Id onto expando target pointers array.
        target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
        // Ensure that the element continues to receive PointerEvents 
        // even if the contact moves off the element. 
        // Capturing the current pointer can improve usability by reducing 
        // the touch precision required when interacting with an element.
        // Note: Only the assigned pointer is affected. 
        target.setPointerCapture(e.pointerId);
    
        // Display pointer details.
        createInfoPop(e);
    }
    
  • Este controlador administra un evento de entrada de puntero (arriba) para un puntero que está en contacto y se mueve dentro de los límites del destino. Agregamos el evento al registro de eventos, agregamos el puntero a la matriz de punteros y mostramos los detalles del puntero.

    Consulta el evento pointermove para controlar el estado mantener de un puntero que no está en contacto pero sí dentro de los límites del destino (normalmente un dispositivo de lápiz o pluma).

    function onPointerOver(e) {
        /// <summary>
        /// Occurs when a pointer is detected within the hit test boundaries 
        /// of an element.
        /// Also occurs prior to a pointerdown event for devices that do not 
        /// support hover.  
        /// This event type is similar to pointerenter, but bubbles. 
        /// See the pointermove event for handling the hover state of a pointer 
        /// that is not in contact but is within the boundary of the target 
        /// (typically a pen/stylus device). 
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details and target UI.
        eventLog.innerText += "\nOver: " + e.pointerId;
    
        if (target.pointers.length === 0) {
            // Change background color of target when pointer contact detected.
            if (e.getCurrentPoint(e.currentTarget).isInContact) {
                // Pointer down occured outside target.
                target.style.backgroundColor = pointerColor.down;
            } else {
                // Pointer down occured inside target.
                target.style.backgroundColor = pointerColor.over;
            }
        }
    
        // Check if pointer already exists.
        for (var i in target.pointers) {
            if (target.pointers[i].id = e.pointerId) {
                return;
            }
        }
    
        // Push new pointer Id onto expando target pointers array.
        target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
        // Ensure that the element continues to receive PointerEvents 
        // even if the contact moves off the element. 
        // Capturing the current pointer can improve usability by reducing 
        // the touch precision required when interacting with an element.
        // Note: Only the assigned pointer is affected. 
        target.setPointerCapture(e.pointerId);
    
        // Display pointer details.
        createInfoPop(e);
    }
    
  • Este controlador administra un evento de movimiento de puntero. Agregamos el evento al registro de eventos y actualizados los detalles del puntero (para mantener, también agregamos el puntero a la matriz de punteros).

    MSPointerHover ya no se utiliza en Windows 8.1. Usa pointermove y la propiedad de puntero IsInContact para determinar el estado mantener.

    Nota   En este controlador, también se procesan varios clics simultáneos de botones del mouse. La entrada de mouse se asocia con un solo puntero asignado al detectar por primera vez la entrada de mouse. Al hacer clic en otros botones del mouse (secundario, rueda o primario) durante la interacción, se crean asociaciones secundarias entre el puntero y esos botones mediante el evento PointerPressed. El evento PointerReleased solo se activa cuando se suelta el último botón del mouse asociado con la interacción (no necesariamente el botón inicial) . Debido a esta asociación exclusiva, los clics de otros botones del mouse se enrutan mediante el evento PointerMove.

     

     function onPointerMove(e) {
         /// <summary>
         /// Occurs when a pointer moves within the hit test boundaries 
         /// of an element.
         /// </summary>
         /// <param name="e" type="Event">The event argument.</param>
    
         // NOTE: Multiple, simultaneous mouse button inputs are processed here.
         // Mouse input is associated with a single pointer assigned when 
         // mouse input is first detected. 
         // Clicking additional mouse buttons (left, wheel, or right) during 
         // the interaction creates secondary associations between those buttons 
         // and the pointer through the pointer pressed event. 
         // The pointer released event is fired only when the last mouse button 
         // associated with the interaction (not necessarily the initial button) 
         // is released. 
         // Because of this exclusive association, other mouse button clicks are 
         // routed through the pointer move event.  
    
         // Prevent the next handler in the hierarchy from receiving the event.
         e.cancelBubble = true;
    
         if (e.pointerType == "mouse") {
             // Mouse button states are extended PointerPoint properties.
             var pt = e.getCurrentPoint(e.currentTarget);
             var ptProperties = pt.properties;
             if (ptProperties.isLeftButtonPressed) {
                 eventLog.innerText += "\nLeft button: " + e.pointerId;
             }
             if (ptProperties.isMiddleButtonPressed) {
                 eventLog.innerText += "\nWheel button: " + e.pointerId;
             }
             if (ptProperties.isRightButtonPressed) {
                 eventLog.innerText += "\nRight button: " + e.pointerId;
             }
         }
         // Handle hover state of a pointer that is not in contact but is within 
         // the boundary of the target (typically a pen/stylus device). 
         if (e.pointerType == "pen") {
             var pt = e.getCurrentPoint(e.currentTarget);
             if (pt.isInContact == false) {
                 // Update event details and target UI.
                 target.style.backgroundColor = pointerColor.hover;
                 eventLog.innerText = "\nHover: " + e.pointerId;
    
                 // Check if pointer already exists.
                 for (var i in target.pointers) {
                     if (target.pointers[i].id = e.pointerId) {
                         updateInfoPop(e);
                         return;
                     }
                 }
    
                 target.pointers.push({ id: e.pointerId, type: e.pointerType });
    
                 // Ensure that the element continues to receive PointerEvents 
                 // even if the contact moves off the element. 
                 // Capturing the current pointer can improve usability by reducing 
                 // the touch precision required when interacting with an element.
                 // Note: Only the assigned pointer is affected. 
                 target.setPointerCapture(e.pointerId);
             }
         }
    
         // Display pointer details.
         updateInfoPop(e);
     }
    
  • Este controlador administra un evento MouseWheel (rotación). Agregamos el evento al registro de eventos, agregamos el puntero a la matriz de punteros (si es necesario) y mostramos los detalles del puntero.

    function onMouseWheel(e) {
        /// <summary>  
        /// Occurs when the mouse wheel is rotated. 
        /// </summary> 
        /// <param name="e" type="Event">The event argument.</param>
        // Check if a mouse pointer already exists.
        for (var i in target.pointers) {
            // Ensure existing pointer type registered with pointerover is mouse. 
            if (target.pointers[i].type === "mouse") {
                e.pointerId = target.pointers[i].id;
                break;
            }
        }
        eventLog.innerText += "\nMouse wheel: " + e.pointerId;
        // For this example, we fire a corresponding pointer down event.
        onPointerDown(e);
    }
    
  • Este controlador administra un evento de salida (arriba) de puntero. Agregamos el evento al registro de eventos, quitamos el puntero de la matriz de punteros y actualizamos los detalles del puntero.

    function onPointerUp(e) {
        /// <summary>
        /// Occurs for mouse at transition from at least one button pressed 
        /// to no buttons pressed.
        /// Occurs for touch and pen when contact is removed from the digitizer. 
        /// For input devices that do not support hover, the pointerout event 
        /// is fired immediately after the pointerup event.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nUp: " + e.pointerId;
    
        // If event source is mouse pointer and the pointer is still 
        // over the target, retain pointer and pointer details.
        // Return without removing pointer from pointers dictionary.
        // For this example, we assume a maximum of one mouse pointer.
        if ((e.pointerType === "mouse") &
            (document.elementFromPoint(e.x, e.y) === target)) {
            target.style.backgroundColor = pointerColor.up;
            return;
        }
    
        // Ensure capture is released on a pointer up event.
        target.releasePointerCapture(e.pointerId);
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
            }
        }
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.up;
        }
    }
    
  • Este controlador administra un evento de salida (afuera) de puntero. Agregamos el evento al registro de eventos, quitamos el puntero de la matriz de punteros y actualizamos los detalles del puntero.

    function onPointerOut(e) {
        /// <summary>
        /// Occurs when a pointer (in contact or not) moves out of the 
        /// target hit test boundary, after a pointerup event for a device 
        /// that does not support hover, and after a pointercancel event. 
        /// This event type is similar to pointerleave, but bubbles.  
        /// Note: Pointer capture is maintained until pointer up event.
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nPointer out: " + e.pointerId;
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
    
                // Update target UI.
                if (target.pointers.length === 0) {
                    target.style.backgroundColor = pointerColor.out;
                }
            }
        }
    }
    
  • Este controlador administra un evento de cancelación de puntero. Agregamos el evento al registro de eventos, quitamos el puntero de la matriz de punteros y actualizamos los detalles del puntero.

    function onPointerCancel(e) {
        /// <summary>
        /// Occurs when a pointer is removed.
        /// The app will not receive subsequent events for that pointer, including pointerup.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // A pointer can be canceled as a result of one of the following:
        //    - A touch contact is canceled when a pen is detected.
        //    - More than 100ms has passed since the device reported
        //      an active contact.
        //    - The desktop is locked or the user logged off. 
        //    - The number of simultaneous contacts exceeds the number 
        //      supported by the device.
        //    - The system has determined that a pointer is unlikely to 
        //      continue to produce events (for example, due to a hardware event).
        //    - After a pointerdown event, the pointer is subsequently used to 
        //      manipulate the page viewport (for example, panning or zooming).  
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nPointer canceled: " + e.pointerId;
    
        // Ensure capture is released on a pointer cancel event.
        target.releasePointerCapture(e.pointerId);
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.cancel;
        }
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
    
                // Update target UI.
                if (target.pointers.length === 0) {
                    target.style.backgroundColor = pointerColor.out;
                }
            }
        }
    }
    
  • Este controlador administra un evento de captura de puntero perdido. Agregamos el evento al registro de eventos, quitamos el puntero de la matriz de punteros y actualizamos los detalles del puntero.

    Nota  lostpointercapture puede producirse en lugar de pointerup. Puede perderse la captura de puntero debido a las interacciones de usuario o porque se capturó mediante programación otro puntero o se liberó intencionalmente la captura del puntero actual.

     

    function onLostPointerCapture(e) {
        /// <summary>
        /// Occurs after pointer capture is released for the pointer.  
        /// </summary>
        /// <param name="e" type="Event">The event argument.</param>
    
        // lostpointercapture can fire instead of pointerup. 
    
        // Pointer capture can be lost as a result of one of the following:
        //    - User interactions
        //    - Programmatic caputre of another pointer
        //    - Captured pointer was deliberately released
    
        // Prevent the next handler in the hierarchy from receiving the event.
        e.cancelBubble = true;
    
        // Update event details.
        eventLog.innerText += "\nLost pointer capture: " + e.pointerId;
    
        // We need the device type to handle lost pointer capture from mouse input.
        // Use the getCurrentPoint method over currentPoint property to ensure
        // the coordinate space is in relation to the target element.
        // Note: getCurrentPoint and currentPoint are only available in the 
        // local compartment, they are not available in the web compartment.
        var ptTarget = e.getCurrentPoint(e.currentTarget);
        var ptContainer = e.getCurrentPoint(document.getElementsByTagName("body")[0]);
    
        // If event source is mouse pointer and the pointer is still over 
        // the target, retain pointer and pointer details.
        // For this example, we assume only one mouse pointer.
        if ((ptTarget.pointerDevice.pointerDeviceType === Windows.Devices.Input.PointerDeviceType.mouse) &
            (document.elementFromPoint(ptContainer.position.x, ptContainer.position.y) === target)) {
            target.setPointerCapture(e.pointerId);
            return;
        }
    
        // Remove pointer from pointers dictionary.
        var targetPointers = target.pointers;
        for (var i in targetPointers) {
            if (target.pointers[i].id === e.pointerId) {
                target.pointers.splice(i, 1);
                var pointerInfoPop = document.getElementById("infoPop" + e.pointerId);
                if (pointerInfoPop === null)
                    return;
                pointerInfoPop.removeNode(true);
            }
        }
    
        // Update target UI.
        if (target.pointers.length === 0) {
            target.style.backgroundColor = pointerColor.cancel;
        }
    }
    

Obtener las propiedades del puntero

El marco de lenguaje que elijas para tu aplicación determina el modo en que se obtienen las propiedades de los punteros. Muchas propiedades se exponen directamente mediante el objeto de evento de puntero. Como se indicó anteriormente, se puede obtener información de puntero adicional mediante los métodos getCurrentPoint y getIntermediatePoints o las propiedades currentPoint y intermediatePoints del argumento de evento. Te recomendamos usar los métodos getCurrentPoint y getIntermediatePoints, que permiten especificar el contexto de los datos de puntero.

Aquí, consultamos varias propiedades de puntero directamente desde el objeto de evento y las propiedades extendidas disponibles únicamente mediante los objetos PointerPoint y PointerPointProperties.

function queryPointer(e) {
    /// <summary>
    /// Get extended pointer data.
    /// </summary>
    /// <param name="e" type="Event">The event argument.</param>

    // We get the extended pointer info through the getCurrentPoint method
    // of the event argument. (We recommend using getCurrentPoint 
    // to ensure the coordinate space is in relation to the target.)
    // Note: getCurrentPoint and currentPoint are only available in the 
    // local compartment, they are not available in the web compartment.

    var pt = e.getCurrentPoint(e.currentTarget);
    var ptTargetProperties = pt.properties;

    var details = "Pointer Id: " + e.pointerId;
    switch (e.pointerType) {
        case "mouse":
            details += "\nPointer type: mouse";
            details += "\nLeft button: " + ptTargetProperties.isLeftButtonPressed;
            details += "\nRight button: " + ptTargetProperties.isRightButtonPressed;
            details += "\nWheel button: " + ptTargetProperties.isMiddleButtonPressed;
            details += "\nX1 button: " + ptTargetProperties.isXButton1Pressed;
            details += "\nX2 button: " + ptTargetProperties.isXButton2Pressed;
            break;
        case "pen":
            details += "\nPointer type: pen";
            if (pt.isInContact) {
                details += "\nPressure: " + ptTargetProperties.pressure;
                details += "\nrotation: " + ptTargetProperties.rotation;
                details += "\nTilt X: " + ptTargetProperties.xtilt;
                details += "\nTilt Y: " + ptTargetProperties.ytilt;
                details += "\nBarrel button pressed: " + ptTargetProperties.isBarrelButtonPressed;
            }
            break;
        case "touch":
            details += "\nPointer type: touch";
            details += "\nPressure: " + ptTargetProperties.pressure;
            details += "\nrotation: " + ptTargetProperties.rotation;
            details += "\nTilt X: " + ptTargetProperties.xtilt;
            details += "\nTilt Y: " + ptTargetProperties.ytilt;
            break;
        default:
            details += "\nPointer type: " + "n/a";
            break;
    }
    details += "\nPointer location (target): " + e.offsetX + ", " + e.offsetY;
    details += "\nPointer location (screen): " + e.screenX + ", " + e.screenY;

    return details;
}

Consulta Temas relacionados en la parte inferior de esta página para obtener vínculos a muestras más complejas.

Ejemplo completo

Consulta Código completo de punteros.

Resumen y siguientes pasos

En este inicio rápido, aprendiste acerca de la entrada de punteros en aplicaciones con JavaScript.

Los eventos de puntero son útiles para administrar interacciones simples como pulsación, deslizamiento y demás interacciones específicas del dispositivo que incluyen la entrada desde botones de mouse secundarios, la rueda del mouse, botones de menú contextual de pluma y el borrador de la pluma.

Para controlar interacciones más elaboradas, como los gestos descritos en el lenguaje táctil de Windows 8, consulta los temas de inicio rápido: gestos y manipulaciones de DOM, inicio rápido: gestos estáticos e inicio rápido: gestos de manipulación.

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

Temas relacionados

Desarrolladores

Responder a la interacción del usuario

Desarrollar aplicaciones de la Tienda Windows (JavaScript y HTML)

Inicio rápido: gestos y manipulaciones de DOM

Inicio rápido: gestos estáticos

Inicio rápido: gestos de manipulación

Diseñadores

Diseño de la interacción táctil