Краткое руководство: жесты управления (HTML)

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. При разработке приложений для Windows 10 см. раздел последняя документация]

Вы можете изменить механизм взаимодействия пользователя для жестов управления, описанных в языке касаний Windows, таких как скольжение, прокрутка, вращение, сжатие и растяжение. Для этого в приложении вам необходимо обрабатывать события жестов среды выполнения Windows с использованием JavaScript.

Большинство приложений обрабатывают жесты касания (поворота, масштабирования и перетаскивания), а необработанные данные указателя просто передают средству обнаружения жестов, не используя их никаким иным образом. В этом примере мы используем необработанные данные указателя для поддержки обработки статического жеста. Это дополняет модель взаимодействия вашего приложения базовыми событиями указателя, о которых говорится в разделе Краткое руководство: указатели.

Обновления в Windows 8.1: В Windows 8.1 появилось множество обновлений и усовершенствований API ввода с помощью указателя. Подробнее: Изменения API для Windows 8.1.

Если у вас нет опыта в разработке приложений на JavaScript: Прочитайте эти разделы, чтобы ознакомиться с технологиями, обсуждаемыми в данной статье.

Создание первого приложения на JavaScript

Схема создания приложений на JavaScript

Информацию о событиях см. в разделе Краткое руководство: добавление элементов управления HTML и обработчиков событий

Компоненты приложения от начала до конца:

Дополнительные сведения об этой функциональности см. в нашей серии Компоненты приложения от начала до конца.

Взаимодействие с пользователем от А до Я (HTML)

Настройка взаимодействия с пользователем от А до Я (HTML)

Рекомендации по взаимодействию с пользователем:

Библиотеки элементов управления платформы (HTML и XAML) предоставляют все механизмы взаимодействия с пользователем, в том числе стандартные взаимодействия, анимированные физические эффекты и визуальную обратную связь. Если вы не планируете настраивать механизмы поддержки взаимодействий, используйте стандартные элементы управления.

Если элементов управления, предоставляемых платформой, недостаточно, то, чтобы обеспечить привлекательный и современный единый механизм взаимодействия для всех режимов ввода, вы можете воспользоваться следующими рекомендациями. В основном эти рекомендации описывают сенсорный ввод, но также применимы к вводу с сенсорной панели, мыши, клавиатуры и пера.

Примеры: Примеры использования этой функциональности см. в коллекции примеров приложений.

Пример настройки взаимодействия с пользователем от А до Я

Ввод: пример обработки событий указателя DOM

Ввод: пример реализации манипуляций и жестов (JavaScript)

Цель: Описывается ожидание и обработка жестов управления на основе данных, вводимых с помощью касания, мыши, пера, и событий жестов среды выполнения Windows.

Необходимые условия

См. Краткое руководство: указатели, Краткое руководство: жесты и манипуляции модели DOM и Краткое руководство: статические жесты.

Предполагается, что вы умеете создавать простые приложения на JavaScript с использованием шаблона библиотеки Windows для JavaScript.

Для выполнения этого руководства вам необходимо:

Что такое события жестов?

Жест — это физическое действие или движение, выполненное при помощи устройства ввода. Это понятие включает в себя один или несколько пальцев на поверхности касания, пера, дигитайзера, мыши и т. д. Такое естественное взаимодействие сопоставляется с операциями над элементами системы и вашего приложения. См. также раздел Жесты, манипуляции и взаимодействия.

В таблице ниже определяются жесты управления, рассмотренные в этом кратком руководстве. Чтобы получить информацию о поддержке статических жестов, таких как касание или нажатие и удерживание, см. раздел Краткое руководство: статические жесты.

ЖестОписание
СкольжениеЖест скольжения

Один или более контактов, перемещающихся за пределы порогового значения расстояния.

Если функция сдвига не включена, а первоначальный контакт находится в границах элемента, жест скольжения приводит к перемещению элемента.

Если функция сдвига включена, первоначальный контакт находится в границах элемента, а направление скольжения перпендикулярно оси сдвига, то жест скольжения также приводит к перемещению элемента. В противном случае инициируется функция сдвига.

  • Состояние на входе: обнаружен один или более контактов.
  • Движение: скользящее/перетаскивающее, пересекает пороговое значение расстояния.
  • Состояние на выходе: последний контакт потерян или прерван.
ПрокруткаЖест прокрутки

Один или несколько контактов, перемещающихся в пределах порогового значения расстояния (короткий скользящий жест). Прокрутка не является жестом, обработка которого определяется временем или скоростью.

Если приложение не поддерживает функцию сдвига, а первоначальный контакт находится в границах элемента, жест прокрутки приводит к перемещению элемента.

Если приложение поддерживает функцию сдвига, первоначальный контакт находится в границах элемента, а направление прокрутки перпендикулярно оси сдвига, то жест прокрутки приводит к выбору элемента. В противном случае жест прокрутки инициирует функцию сдвига.

  • Состояние на входе: обнаружен один или более контактов.
  • Движение: скользящее/перетаскивающее, не пересекает пороговое значение расстояния.
  • Состояние на выходе: последний контакт потерян или прерван.
Сжатие и растяжениеЖест сжатия и растяжения

Два или более контактов, которые сходятся или расходятся для увеличения или уменьшения элемента соответственно.

Обычно используется для изменения размеров объекта, его увеличения или уменьшения или для контекстного масштабирования.

  • Состояние на входе: обнаружено два или более контактов в ограничивающей объект прямоугольной области.
  • Движение: перетаскивающее/скользящее; контакты сходятся или расходятся.
  • Состояние на выходе: обнаружено менее двух контактов.
ВращениеЖест вращения

Вращение нескольких пальцев на экране приводит к повороту объекта. Чтобы повернуть весь экран, поверните само устройство.

Два или более контактов, которые перемещаются по кругу вокруг центра (или точки) поворота.

Обычно используется для поворота объекта.

  • Состояние на входе: обнаружено два или более контактов в ограничивающей объект прямоугольной области.
  • Движение: перетаскивающее/скользящее; один или более контактов перемещаются по кругу.
  • Состояние на выходе: обнаружено менее двух контактов.

Подробнее об этих жестах и их отношении к языку касаний Windows 8 см. в разделе Взаимодействие с помощью сенсорного ввода.

 

Важно  Если вы реализуете собственную поддержку взаимодействий, помните: пользователи ожидают, что способ взаимодействия с элементами вашего приложения будет интуитивно понятным. Рекомендуется моделирование взаимодействий с пользователем на базе библиотек элементов управления платформы (HTML и XAML) для единообразия элементов и возможности их обнаруживать. Элементы управления в этих библиотеках предоставляют все механизмы взаимодействия с пользователем, в том числе стандартные взаимодействия, анимированные физические эффекты, визуальную обратную связь и специальные возможности. Создавайте пользовательские взаимодействия, только если они действительно необходимы и если ни один стандартный механизм взаимодействия не подходит для вашего сценария.

 

Создание пользовательского интерфейса

В следующем примере демонстрируется добавление в базовый элемент пользовательского интерфейса отдельного жеста — вращения для поворота. Квадрат (target) действует как целевой объект для ввода и определения указателя. Эти данные указателя передаются объекту GestureRecognizer, который обрабатывает данные жеста вращения, чтобы создать вращающуюся операцию со стандартным инерционным поведением.

Приложение предоставляет следующие функциональные возможности взаимодействия с пользователем.

  • Вращение: поворачивается объект, причем поворот не прекращается после прекращения контакта с указателем. Подобное поведение взаимодействия соответствует Рекомендациям по визуальной обратной связи и рекомендациям языка касаний Windows. Согласно этим рекомендациям жест поворота должен быть ограничен областью поворота элементов пользовательского интерфейса. Примечание  Этот пример легко изменить для разработки поддержки перетаскивания и масштабирования. Далее мы рассмотрим это в данном кратком руководстве.  

HTML-код для этого примера.

<html>
<head>
    <meta charset="utf-8" />
    <title>Manipulation Gestures</title>
    
    <!-- WinJS references -->
    <link rel="stylesheet" href="//Microsoft.WinJS.2.0/css/ui-light.css" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- BasicGesture references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/InputProcessor.js"></script>
    <script src="/js/ManipulationManager.js"></script>
    <script src="/js/default.js"></script>
</head>
<body>
    <div class="Container" id="Container">
        <div id="targetTitle">Manipulation gestures (rotation)</div>
        <div class="TargetContainer" id="targetContainer">
            <div id="target" draggable="false"></div>
        </div>
        <div id="targetFooter">&nbsp;</div>
    </div>
</body>
</html>

Код каскадных таблиц стилей (CSS) для этого примера.

Примечание  События указателя не генерируются в процессе взаимодействий сдвига или масштабирования. Сдвиг и масштабирование для области можно отключить при помощи таких свойств CSS, как msTouchAction, overflow и -ms-content-zooming.

 

html,body {
    overflow: hidden;
    position: relative;
    height: 100%;
}

div #Container {
/*
This element permits no default touch behaviors.
A manipulation-blocking element is defined as an element that explicitly 
blocks direct manipulation via declarative markup, and instead fires gesture 
events such as MSGestureStart, MSGestureChange, and MSGestureEnd.
*/
    touch-action: none;
    display: -ms-grid;
    -ms-grid-rows: 200px 1fr 50px;
    -ms-grid-columns: 1fr;
    overflow: hidden;
    position: absolute;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}

div #targetTitle {
    touch-action: none;
    -ms-grid-row: 1;
    -ms-grid-column: 1;
    background-color: black;
    color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
    font-family: 'Segoe UI';
    font-size: large;
}
div #targetContainer {
    touch-action: none;
    -ms-grid-row: 2;
    -ms-grid-column: 1;
    background-color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}
div #targetFooter {
    touch-action: none;
    -ms-grid-row: 3;
    -ms-grid-column: 1;
    background-color: black;
    color: white;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
    font-family: 'Segoe UI';
    font-size: large;
}

div #target {
    -ms-transform-origin: 0px 0px;
    position: absolute;
    width: 300px;
    height: 300px;
    background-color: black;
    padding: 0px;
    margin: 0px;
    border-width: 0px;
    border-collapse: collapse;
}

Инициализация приложения

Задайте целевой объект, его контейнер и обработку операций для целевого объекта при запуске приложения.

Здесь мы инициализируем целевой элемент (и другие объекты пользовательского интерфейса) в контейнере и настроим обработчик для операций.

/// <summary> 
/// Initializes the target and manipulation handling.
/// </summary>
function initialize() {
    var container = document.getElementById("targetContainer");
    var target = document.getElementById("target");
    var title = document.getElementById("targetTitle");
    var footer = document.getElementById("targetFooter");
    // Set the height of the target container for initial positioning of the target.
    var containerHeight = window.innerHeight - title.clientHeight - footer.clientHeight;
    container.style.height = containerHeight + "px";
    // Set the initial position of the target.
    target.style.msTransform = (new MSCSSMatrix()).
        translate((container.clientWidth - parseInt(target.clientWidth)) / 2.0,
        (containerHeight - parseInt(target.clientHeight)) / 2.0);
    // Configure manipulation handling.
    var manipulable = new Manipulator.ManipulationManager();
    // The configuration function can support all manipulations.
    // For this example, we limit manipulation support to rotation with inertia.
    manipulable.configure(false,
                          true, // Rotation.
                          false,
                          true, // Inertia.
                          1,
                          0,
                          {
                              x: (container.clientWidth - parseInt(target.clientWidth)) / 2.0,
                              y: (containerHeight - parseInt(target.clientHeight)) / 2.0
                          });
    manipulable.setElement(target);
    manipulable.setParent(container);
    // Handler for transforms related to the manipulation.
    manipulable.registerMoveHandler({
        x: (container.clientWidth / 2.0),
        y: (containerHeight / 2.0)
    }, Manipulator.ManipulationManager.FixPivot.MoveHandler);
}

Обработка ввода от указателя и настройка распознавателя жестов

Для этого примера мы используем базовый класс-оболочку (InputProcessor) для определения обработчика событий указателя и объекта GestureRecognizer, который принимает ввод от указателя.

В большинстве случаев рекомендуется получать информацию об указателе через аргумент события обработчиков события указателя на выбранном языке платформы.

Если аргумент события не предоставляет данных указателя, необходимых для приложения, можно получить доступ к расширенным данным указателя через аргумент события с помощью методов getCurrentPoint и getIntermediatePoints или свойств currentPoint и intermediatePoints. Рекомендуется использовать методы getCurrentPoint и getIntermediatePoints, так как для них можно указать контекст указателя данных.

Совет  В данном примере только один объект сопоставляется с распознавателем жестов. Если ваше приложение содержит большое количество объектов, которыми можно управлять (например, головоломка), рассмотрите возможность динамического создания распознавателя жестов только в моменты, когда на конечном объекте определяется ввод с помощью указателя. Распознаватель жестов может быть удален при завершении всех операций (см. пример жестов, который допускает создание экземпляров). Чтобы сократить временные затраты на создание и удаление распознавателей жестов, создайте небольшой пул распознавателей жестов при инициализации и динамически распределяйте их по мере необходимости.

 

Распознаватель жестов (_gestureRecognizer) прослушивает и обрабатывает все события указателя и жестов.

/// <summary> 
/// InputProcessor is a thin wrapper for pointer event handling and gesture detection.
/// Defines an InputProcessor class that takes all pointer event data and feeds it to
/// a GestureRecognizer for processing of the manipulation gestures 
/// as configured in ManipulationManager.js.
/// </summary>
(function () {
    "use strict";
    WinJS.Namespace.define("Manipulator", {
        InputProcessor: WinJS.Class.define(function () {
            // Constructor.
            this._gestureRecognizer = new Windows.UI.Input.GestureRecognizer();
            this._downPoint = null;
            this._lastState = null;
        }, {
            // Instance members.
            element: {
                /// <summary> 
                /// The manipulable element.
                /// </summary>
                get: function () {
                    if (!this._element) {
                        return null;
                    }
                    return this._element;
                },
                set: function (value) {
                    this._element = value;
                    this._setupElement();
                }
            },
            parent: {
                /// <summary> 
                /// The container that defines the coordinate space used
                /// for transformations during manipulation of the target.
                /// </summary>
                get: function () {
                    if (!this._parent) {
                        return null;
                    }
                    return this._parent;
                },
                set: function (value) {
                    this._parent = value;
                }
            },
            getRecognizer: function () {
                /// <summary>
                /// The gesture recognition object.
                /// </summary>
                return this._gestureRecognizer;
            },
            getDown: function () {
                /// <summary>
                /// The pointer data for the pointerdown event.
                /// </summary>
                return this._downPoint;
            },
            _setupElement: function () {
                /// <summary> 
                /// Declare the event listeners for the pointer events on the target.
                /// </summary>
                var that = this;
                this._element.addEventListener("pointerdown",
                    function (evt) { Manipulator.InputProcessor._handleDown(that, evt); },
                    false);
                this._element.addEventListener("pointermove",
                    function (evt) { Manipulator.InputProcessor._handleMove(that, evt); },
                    false);
                this._element.addEventListener("pointerup",
                    function (evt) { Manipulator.InputProcessor._handleUp(that, evt); },
                    false);
                this._element.addEventListener("pointercancel",
                    function (evt) { Manipulator.InputProcessor._handleCancel(that, evt); },
                    false);
                this._element.addEventListener("wheel",
                    function (evt) { Manipulator.InputProcessor._handleMouse(that, evt); },
                    false);
            }
        }, {
            // Static members.
            _handleDown: function (that, evt) {
                /// <summary> 
                /// Handler for the pointerdown event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._element.setPointerCapture(pp.pointerId);
                that._gestureRecognizer.processDownEvent(pp);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();

                // Capture the pointer location for this event.
                that._downPoint = { x: pp.position.x, y: pp.position.y };
            },
            _handleMove: function (that, evt) {
                /// <summary> 
                /// Handler for the pointermove event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pps = evt.getIntermediatePoints(that._parent);
                that._gestureRecognizer.processMoveEvents(pps);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleUp: function (that, evt) {
                /// <summary> 
                /// Handler for the pointerup event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._gestureRecognizer.processUpEvent(pp);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleCancel: function (that, evt) {
                /// <summary> 
                /// Handler for the pointercancel event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                that._gestureRecognizer.completeGesture();

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
            },
            _handleMouse: function (that, evt) {
                /// <summary> 
                /// Handler for the mouse wheel event.
                /// </summary>
                /// <param name="that" type="Object">
                /// The InputProcessor object handling this event.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event object.
                /// </param>
                var pp = evt.getCurrentPoint(that._parent);
                that._gestureRecognizer.processMouseWheelEvent(pp, evt.shiftKey, evt.ctrlKey);

                // Prevent propagation of this event to additional event handlers.
                evt.stopImmediatePropagation();
                evt.preventDefault();
            }
        })
    });
})();

Обработка манипуляции

Здесь мы используем класс диспетчера манипуляций (ManipulationManager) для определения поведения манипуляции и ограничений для объекта GestureRecognizer. Этот объект был определен в InputProcessor (_inputProcessor), описанном на предыдущем этапе.

/// <summary> 
/// ManipulationManager is the manipulation processing engine for the 
/// GestureRecognizer object defined in InputProcessor.js.
/// Different components and behaviors of manipulation (rotate, translate, zoom, 
/// and inertia) can be enabled, disabled, and customized as required.
/// </summary>
(function () {
    "use strict";
    WinJS.Namespace.define("Manipulator", {
        ManipulationManager: WinJS.Class.define(function () {
            // Constructor.
            // Create an input processor.
            this._inputProcessor = new Manipulator.InputProcessor();
            // Initialize the manipulation movement and end handlers.
            this._endHandler = null;
            this._moveHandler = null;
            // Create the transform matrices used for manipulating
            // and resetting the target.
            this._currentTransform = new MSCSSMatrix();
            this._initialTransform = new MSCSSMatrix();
            // Initialize the transform matrices values.
            this._initialTransformParams = {
                translation: { x: 0, y: 0 },
                rotation: 0,
                scale: 1
            };
            this._currentTransformParams = {
                translation: { x: 0, y: 0 },
                rotation: 0,
                scale: 1
            };
        }, {
            // Instance members.
            configure: function (scale, rotate, translate, inertia,
                                initialScale, initialRotate, initialTranslate) {
                /// <summary> 
                /// Define the behaviors of the ManipulationManager object.
                /// </summary>
                /// <param name="scale" type="Boolean">
                /// True if scaling is enabled.
                /// </param>
                /// <param name="rotate" type="Boolean">
                /// True if rotation is enabled.
                /// </param>
                /// <param name="translate" type="Boolean">
                /// True if translation is enabled.
                /// </param>
                /// <param name="inertia" type="Boolean">
                /// True if inertia is enabled.
                /// </param>
                /// <param name="initialScale" type="Number">
                /// The initial scale factor.
                /// </param>
                /// <param name="initialRotate" type="Number">
                /// The initial rotation value.
                /// </param>
                /// <param name="initialTranslate" type="Object">
                /// The initial translation values (x,y).
                /// </param>

                // Get the GestureRecognizer associated with this manipulation manager.
                var gr = this._inputProcessor.getRecognizer();
                // Set the manipulations supported by the GestureRecognizer if the
                // interaction is not already being processed.
                if (!gr.isActive) {
                    var settings = 0;
                    if (scale) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationScale;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationScaleInertia;
                        }
                    }
                    if (rotate) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationRotate;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationRotateInertia;
                        }
                    }
                    if (translate) {
                        settings |= Windows.UI.Input.GestureSettings.manipulationTranslateX |
                            Windows.UI.Input.GestureSettings.manipulationTranslateY;
                        if (inertia) {
                            settings |= Windows.UI.Input.GestureSettings.manipulationTranslateInertia;
                        }
                    }

                    // Cache a reference to the current object.
                    var that = this;

                    // If any manipulation is supported, declare the manipulation event listeners.
                    if (scale || rotate || translate) {
                        gr.addEventListener('manipulationstarted',
                            function (evt) { Manipulator.ManipulationManager._manipulationStarted(that, evt); },
                            false);
                        gr.addEventListener('manipulationupdated',
                            function (evt) { Manipulator.ManipulationManager._manipulationUpdated(that, evt); },
                            false);
                        gr.addEventListener('manipulationended',
                            function (evt) { Manipulator.ManipulationManager._manipulationEnded(that, evt); },
                            false);
                    }

                    gr.gestureSettings = settings;

                    // Initialize the transform matrices.
                    this._currentTransformParams.scale = initialScale;
                    this._currentTransformParams.rotation = initialRotate;
                    this._currentTransformParams.translation = initialTranslate;

                    this._initialTransformParams.scale = initialScale;
                    this._initialTransformParams.rotation = initialRotate;
                    this._initialTransformParams.translation = initialTranslate;

                    // Set the transformation values.
                    if (initialRotate) {
                        this._initialTransform = this._initialTransform.rotate(initialRotate);
                    }
                    else {
                        this._currentTransformParams.rotation = 0;
                        this._initialTransformParams.rotation = 0;
                    }
                    if (initialTranslate) {
                        this._initialTransform = this._initialTransform.translate(initialTranslate.x, initialTranslate.y);
                    }
                    else {
                        this._currentTransformParams.translation = { x: 0, y: 0 };
                        this._initialTransformParams.translation = { x: 0, y: 0 };
                    }
                    if (initialScale) {
                        this._initialTransform = this._initialTransform.scale(initialScale);
                    }
                    else {
                        this._currentTransformParams.scale = 1;
                        this._initialTransformParams.scale = 1;
                    }

                    this._currentTransform = this._initialTransform;
                }
            },
            setElement: function (elm) {
                /// <summary> 
                /// Set the manipulable object.
                /// </summary>
                /// <param name="elm" type="Object">
                /// The object that supports manipulation.
                /// </param>
                this._inputProcessor.element = elm;
                // Set the transform origin for rotation and scale manipulations.
                this._inputProcessor.element.style.msTransformOrigin = "0 0";
            },
            setParent: function (elm) {
                /// <summary> 
                /// Set the parent of the manipulable object.
                /// </summary>
                /// <param name="elm" type="Object">
                /// The parent of the object that supports manipulation.
                /// </param>
                this._inputProcessor.parent = elm;
            },
            registerEndHandler: function (handler) {
                /// <summary> 
                /// Register handler to be called after the manipulation is complete.
                /// </summary>
                /// <param name="handler" type="Function">
                /// The manipulationended event handler.
                /// </param>
                this._endHandler = handler;
            },
            registerMoveHandler: function (arg, handler) {
                /// <summary> 
                /// Register handler to be called when manipulation is under way.
                /// </summary>
                /// <param name="args">
                /// Arguments passed to the move handler function.
                /// </param>
                /// <param name="handler" type="Function">
                /// The manipulationupdated event handler.
                /// </param>
                this._moveHandlerArg = arg;
                this._moveHandler = handler;
            },
            resetAllTransforms: function () {
                /// <summary> 
                /// Reset the ManipulationManager object to its initial state.
                /// </summary>

                // Check that the element has been registered before before attempting to reset.
                if (this._inputProcessor.element) {
                    // Reapply the initial transform
                    this._inputProcessor.element.style.transform = this._initialTransform.toString();
                    this._currentTransform = this._initialTransform;

                    // Reset the current transform parameters to their initial values.
                    this._currentTransformParams.translation = this._initialTransformParams.translation;
                    this._currentTransformParams.rotation = this._initialTransformParams.rotation;
                    this._currentTransformParams.scale = this._initialTransformParams.scale;
                }
            },

            _applyMotion: function (pivot, translation, rotation, scaling) {
                /// <summary> 
                /// Apply the manipulation transform to the target.
                /// </summary>
                /// <param name="pivot" type="Object">
                /// The X,Y values for the rotation and scaling pivot point.
                /// </param>
                /// <param name="translation" type="Object">
                /// The X,Y values for the translation delta.
                /// </param>
                /// <param name="rotation" type="Number">
                /// The angle of rotation.
                /// </param>
                /// <param name="scaling" type="Number">
                /// The scaling factor.
                /// </param>

                // Create the transform, apply parameters, and multiply by the current transform matrix.
                var transform = new MSCSSMatrix().translate(pivot.x, pivot.y).
                    translate(translation.x, translation.y).
                    rotate(rotation).
                    scale(scaling).
                    translate(-pivot.x, -pivot.y).multiply(this._currentTransform);

                this._inputProcessor.element.style.transform = transform.toString();
                this._currentTransform = transform;
            },

            _updateTransformParams: function (delta) {
                /// <summary> 
                /// Update the current transformation parameters based on the new delta.
                /// </summary>
                /// <param name="that" type="Object">
                /// The change in rotation, scaling, and translation.
                /// </param>
                this._currentTransformParams.translation.x = this._currentTransformParams.translation.x + delta.translation.x;
                this._currentTransformParams.translation.y = this._currentTransformParams.translation.y + delta.translation.y;
                this._currentTransformParams.rotation = this._currentTransformParams.rotation + delta.rotation;
                this._currentTransformParams.scale = this._currentTransformParams.scale * delta.scale;
            }
        }, {
            // Static members.
            _manipulationStarted: function (that, evt) {
                /// <summary> 
                /// The manipulationstarted event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                Manipulator.ManipulationManager._manipulationHelper(that, evt);
            },
            _manipulationUpdated: function (that, evt) {
                /// <summary> 
                /// The manipulationupdated event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                Manipulator.ManipulationManager._manipulationHelper(that, evt);
            },
            _manipulationEnded: function (that, evt) {
                /// <summary> 
                /// The manipulationended event handler.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>
                // Pass the event to the manipulation helper function.
                Manipulator.ManipulationManager._manipulationHelper(that, evt);

                // Call the manipulationended handler, if registered.
                if (that._endHandler) {
                    that._endHandler();
                }
            },
            _manipulationHelper: function (that, evt) {
                /// <summary> 
                /// Helper function for calculating and applying the transformation parameter deltas.
                /// </summary>
                /// <param name="that" type="Object">
                /// ManipulationManager object on which the event was performed.
                /// </param>
                /// <param name="evt" type="Event">
                /// The event data.
                /// </param>

                if (evt.delta) {
                    // Rotation/scaling pivot point.
                    var pivot = { x: evt.position.x, y: evt.position.y };

                    // Translation values.
                    var translation = { x: evt.delta.translation.x, y: evt.delta.translation.y };

                    // Rotation angle.
                    var rotation = evt.delta.rotation;

                    // Scale factor.
                    var scale = evt.delta.scale;

                    // Group the transformation parameter deltas.
                    var delta = {
                        pivot: pivot,
                        translation: translation,
                        rotation: rotation,
                        scale: scale
                    };

                    // Apply the manipulation movement constraints.
                    if (that._moveHandler) {
                        delta = that._moveHandler(that._moveHandlerArg, delta, that._currentTransformParams, that._currentTransform);
                    }

                    // Update the transformation parameters with fresh deltas.
                    that._updateTransformParams(delta);

                    // Apply the transformation.
                    that._applyMotion(delta.pivot, delta.translation, delta.rotation, delta.scale);
                }
            },
            FixPivot: WinJS.Class.define(function () {
            /// <summary>
            /// Constrain the center of manipulation (or pivot point) to a set of X,Y coordinates,  
            /// instead of the centroid of the pointers associated with the manipulation.
            /// <param name="pivot" type="Object">
            /// The pivot coordinates for the ManipulationManager object.
            /// </param>
            /// <param name="delta" type="Object">
            /// The transformation parameter deltas (pivot, delta, rotation, scale).
            /// </param>
            /// </summary>
            }, {
            }, {
                MoveHandler: function (pivot, delta) {
                    delta.pivot = pivot;
                    return delta;
                }
            }),
        })
    });
})();

См. ссылки на более сложные примеры в разделе "Связанные темы" в нижней части страницы.

Полный пример

См. раздел Полный код для жестов управления.

Краткая сводка и дальнейшие действия

Из данного краткого руководства вы узнали об обработке событий жестов манипуляций в приложениях Магазина Windows на JavaScript.

Жесты управления удобны для поддержки сложных взаимодействий, например скольжения для сдвига или перестановки/перемещения и поворота, и управления ими.

Более сложные примеры обработки жестов см. в разделе Ввод: образец пользовательских жестов.

Примечание  Этот пример не соответствует рекомендациям языка касаний Windows в отношении пользовательского взаимодействия. Некоторые статические жесты переопределены в учебных целях.

 

Об управлении статическими взаимодействиями (такими как скольжение, прокрутка, вращение, сжатие и растяжение) см. в разделе Краткое руководство: статические жесты.

Подробнее о языке касания Windows 8 см. в разделе Взаимодействие с помощью сенсорного ввода.

Связанные разделы

Разработчикам

Реакция на взаимодействие с пользователем

Разработка приложений Магазина Windows (JavaScript и HTML)

Краткое руководство: указатели

Краткое руководство: жесты и манипуляции модели DOM

Краткое руководство: статические жесты

Проектировщикам

Взаимодействие с помощью сенсорного ввода