Файлы к данной лекции Вы можете скачать здесь.
Сенсорный экран, безусловно, это одно из самых замечательных средств взаимодействия с компьютером, которое в наши дни, наконец, повзрослело. Конечно, уже много лет у нас есть устройства, которыми можно управлять касаниями. Помню, я работал с экраном, чувствительным к касаниям, в колледже, должен признать, это было до неприличия давно. Тогда сенсорный датчик представлял собой набор прозрачных проводников, встроенных в лист пластика, расположенный над экраном, с общим сенсорным разрешением что-то около 60 точек в ширину и 40 в высоту… и, что действительно выдает давность этих событий, монитор представлял собой полностью текстовый терминал.
К счастью, в последние годы сенсорные экраны чрезвычайно развились. Они достаточно чувствительны для нужд общего назначения (вам не нужно бить по ним, чтобы они зафиксировали событие ввода данных), они встроены в дисплеи высокого разрешения, они сравнительно дешевы, и они могут деть гораздо больше, чем копировать поведение мыши, а именно – они поддерживают множество одновременных касаний и сложные жесты.
Хорошие возможности по сенсорному взаимодействию – это фундаментальная функция отличных приложений, и разработка для сенсорного взаимодействия означает, во многом, переосмысление пользовательского интерфейса. В наших макетах, например, это предусматривает создание целей касания, размер которых подходит для пальцев различного размера. В плане перемещения по содержимому, это подразумевает использование прямых жестов, таких, как протягивание и жесты сжатия и разведения пальцев, вместо того, чтобы полагаться только на выделение элементов и элементы управления для навигации. Аналогично, разработка для сенсорного взаимодействия подразумевает размышление о том, как жесты могут обогатить опыт взаимодействия пользователя и приложения, и так же, как обеспечить возможности по исследованию элементов и обратную связь пользователям, которые привыкли полагаться лишь на события мыши, наподобие зависания указателя над объектом.
В целом, подходите к дизайну так, будто сенсорное взаимодействие – это единственный способ, который есть у пользователя. В то же время, важно помнить, что новые способы ввода редко полностью замещают устаревшие. Конечно, перфокарты, в конечном счете, исчезли, но изобретение мыши не сделало ненужной клавиатуру. Доступность распознавания речи или рукописного ввода не привели к исчезновению мыши и клавиатуры. Я думаю, то же самое справедливо для сенсорного взаимодействия: это дополнительный способ ввода, который имеет собственные особенные преимущества, но вряд ли он полностью вытеснит другие. Как сказал Билл Бакстон из Microsoft Research: "Каждое отдельное явление, включая сенсорное взаимодействие, хорошо подходит для чего-то одного и плохо – для чего-то другого". Я надеюсь, со временем, мы будем использовать клавиатуру, мышь, и сенсорный экран вместе, так же, как мы научились использовать в повседневной работе мышь в те времена, когда единственным средство ввода информации была клавиатура.
Windows спроектирована для хорошей работы со всеми формами ввода – для отличной работы с сенсорным экраном, мышью, клавиатурой, и все это – на разном аппаратном обеспечении! (И сертификация для Магазина Windows требует, чтобы все приложения обладали этими возможностями.) По этоим причинам, Windows предоставляет унифицированную, основанную на указателе (pointer) модель, где вы можете дифференцировать различные способы ввода, если нужно, но можете обрабатывать их все равнозначно. Так же вы можете сосредоточиться на жестах высокого уровня, которые могут исходить из многих источников ввода, и совсем не беспокоиться об исходных событиях указателя. На самом деле, тот факт, что мы не поднимали до сих пор этот вопрос, показывает, как естественно можно работать со всеми видами указателей ввода и не беспокоиться о них: элементы управления и другие части пользовательского интерфейса, которые мы использовали, выполняют за нас всю подобную работу. Необходимость в обработке подобных событий возникает преимущественно при создании собственных элементов управления или для выполнения прямых манипуляций с объектами, которые не являются элементами управления.
Клавиатура – это важный инструмент для ввода данных, это относится и к аппаратной клавиатуре, и к экранной "программной" клавиатуре. Последней уделяется много внимания в наше время, в плане устройств, обладающих лишь возможностями сенсорного взаимодействия с пользователем, но, на самом деле, основные вопросы касались доступности. В Windows, так же, программная клавитура включает в себя возможности распознавания рукописного текста, иногда приложения просто включают в себя эту возможность. И когда приложение нуждается в более плотной работе с исходными данными рукописного ввода (ink), оно так же может воспользоваться этими возможностями.
Другая тема, которой мы коснемся в этой лекции, касается датчиков (сенсоров). До тех пор, пока вы не узнаете, что это за датчики, может показаться непоследовательным помещать эту тему вместе с темой о вводе данных. Датчики, вместе с сенсорным экраном – это еще один способ ввода данных. Сенсоры сообщают приложению, что происходит с устройством во внешнем мире: как оно расположено в пространстве (относительно некоторого количества опорных точек), как оно перемещается в пространстве, как оно расположено по отношению к "нормальной" ориентации, и даже то, насколько яркий свет освещает устройство. Видя сенсоры в таком свете (преднамеренный каламбур), мы начинаем видеть возможности прямой интеграции приложений с окружающим миром вместо того, чтобы нуждаться в том, что пользователь сообщит приложению о внешних условиях каким-то абстрактным способом. Хочу предупредить вас, что как только вы увидите, как легко использовать API WinRT для работы с датчиками, вам может захотеться купить новое устройство, которое хорошо ими оснащено!
Когда речь идет о вводе данных, основанном на указателе, что включает в себя ввод данных с помощью мыши, касаний, ручки и пера – особое сообщение от Microsoft имело и имеет актуальность: "Дизайн приложений, использующих мышь, касания, перо – без дополнительных усилий". Это – очень важно, как мы увидим дальше, но мы так же обнаружили, что фразы вроде "дизайн, ориентированный на касания" ("first-touch design"), хорошо звучащие для потребителей, может выглядеть пугающей для разработчиков! Когда все внимание обращено на взаимодействие с помощью касаний, нужно учитывать, что пользователи весьма требовательны в своих ожиданиях, и для соответствия продукта этим ожиданиям может потребоваться много работы.
К счастью, Windows 8 предоставляет единую платформу для обработки указателя ввода из всех источников, в итоге, вам не нужно особо задумываться об их различиях до тех пор, пока у вас не будет особых причин сделать это. Таким образом, проектирование приложений с учетом соображений дизайна, ориентированного на касания, это – больше вопрос дизайна, чем вопрос программирования.
В следующем разделе мы подробнее поговорим о проектировании приложений для сенсорного взаимодействия. Для начала мне хотелось бы обсудить, как вам, в роли разработчика, следует подходить к реализации подобного дизайна, до тех пор, пока вам не понадобится делать различия между типами указателя:
tabindex для тех пользователей, которые будут применять клавиатуру, назначьте обработчики для стандартных событий DOM, наподобие click, и все готово. Элементы управления наподобие элемента для контекстного масштабирования уже обрабатывают различные виды ввода (как мы видели в лекции 5 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript"), CSS-стили, наподобие точек прикрепления и масштабирования контента обрабатывают различные жесты взаимодействия с приложением.MsGestureTap и MsGestureHold, вместе с последовательностями событий для жестов, использующих инерцию (MSGestureStart, MSGestureChange, и MSGestureEnd). Преимущество здесь в том, что эти жесты представляют собой высокоуровневую интерпретацию низкоуровневых событий указателя, что означает, что вам не нужно выполнять подобную интерпретацию самостоятельно. Например, касание (down) с последующим отрывом, поднятием (up) указателя в пределах определенного порога передвижения (для того, чтобы учеcть шевеление пальцев) становится единым жестом касания (tap). Касание, за которым следует короткое перетаскивание (drag), после чего указатель поднимается, становится жестом прокрутки (swipe), которое вызывает последовательность
событий, возможно, включающих события, указывающие на инерцию (те, которые продолжают вызываться, даже после того, как указатель, наподобие точки касания, физически освобожден). Обратите внимание на то, что если вы хотите захватить и сохранить данные ввода указателя, не обращая внимание на жесты, есть встроенная возможность для рукописного ввода (inking), позже мы ее рассмотрим.MsPointerDown, MsPointerMove и так далее.Это – события более низкого уровня, чем события жестов, и они, преимущественно, подходят для приложений, которые не нуждаются в интерпретации жестов. Например, приложению для рисования нужно просто отследить различные указатели и отобразить их на экране, здесь концепции наподобие прокрутки и инерции значения не имеют. События указателя так же предоставляют специфическую информацию от устройств – такую, как давление, поворот, сдвиг, и они отражаются в событиях указателя. Напомню, возможно реализовать обработку жестов на основе прямой обработки событий указателя, как делает большое количество встроенных элементов управления.А что же о традиционных событиях DOM, которые мы знаем и любим, помимо )). Используйте в коде жесты и события указателя так часто, как сможете.
Примечание. Визуальная обратная связь для сенсорного ввода – это одно из требований к сертификации приложений для Windows 8 (раздел 3.5., http://msdn.microsoft.com/library/windows/apps/hh694083.aspx ), она применима везде в ваших приложениях, так же, как и к любому веб-содержимому, которые вы можете отображать в элементе iframe. Предоставление обратной связи подразумевает исполнение короткой анимации, которая подтверждает касание. Для этих целей вы можете использовать библиотеку анимаций WinJS или, напрямую, CSS-анимации и переходы, как описано в лекции 5.
Весьма обширная статья в Центре разработчиков Windows, "Проектирование взаимодействия с сенсорным экраном" (http://msdn.microsoft.com/library/windows/apps/hh465415.aspx) полезна и для дизайнеров, и для разработчиков. Она посвящена различным соображениям эргономики, содержит несколько хороших изображений, посвященных различным размерам пальцев, предоставляет четкое руководство по подходящим размерам целей касания, продиктованное реальными условиями, и описывает ключевые принципы дизайна, такие, как обеспечение прямой обратной связи для сенсорного взаимодействия (анимации) и то, как содержимое должно следовать за пальцем.
Особенно важно то, что руководство по дизайну так же описывает Язык касаний Windows 8 (Windows 8 Touch Language), который включает в себя восемь основных жестов, которые поддерживаются и системой, и элементами управления. Таблица ниже показывает и описывает эти жесты, и показывает, какие события, воспринимаемые приложением, им соответствуют.
| Жест | Значение и событие жеста | Описание |
|---|---|---|
Палец касается экрана и остается в месте касания ![]() |
Нажатие с удержанием для вывода информации. Выглядит как события элемента contextmenu и MsGestureHold. |
Этот жест предназначен для отображения подробной информации или справочного изображения (например, всплывающей подсказки или контекстного меню без необходимости выполнения действия. Все содержимое, отображаемое таким образом, не должно препятствовать сдвигу объектов пользователями, если они проводят пальцем по экрану. |
Палец касается экрана, после чего поднимается.![]() |
Касание для основного действия (для управления), выглядит как события элемента click и MSGestureTap. |
Касание элемента вызывает его основное действие, обычно – выполнение команды, установку флага, установку оценки, позиционирование курсора и так далее. |
Один или несколько пальцев касаются экрана и перемещаются в одном направлении.![]() |
Скольжение для сдвига (может быть горизонтальным или вертикальным). Выглядит как события прокрутки и как серия событий (MSGestureStart, MSGestureChange, MSGestureEnd, возможно с событиями инерционных жестов, о которых оповещает MSInertiaStart, плюс - события MSPointer*). |
Скольжение используется, главным образом, для сдвига объектов, но так же подходят для перемещений, рисования или рукописного ввода. Скольжение так же можно использовать для выбора мелких элементов, расположенных близко друг к другу. Для этого нужно выполнить жест потирания (scrubbing) (провести пальцем по связанным объектам, таким, как переключатели) |
Один или несколько пальцев касаются экрана и перемещаются на короткое расстояние в одном направлении![]() |
Скольжение для выбора, управления и перемещения (может быть вертикальным или горизонтальным), так же называется скольжением по диагонали (cross-slide), выглядит как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd, так же, как и события MSPointer*). Средство распознавания жестов, однако, не отличает этот жест от вертикального сдвига, поэтому приложение или элемент управления нуждаются в прямой реализации подобной интерпретации (хорошая причина для использования элементов управления наподобие ListView!) |
Если прочертить пальцем короткий отрезок, перпендикулярный направлению сдвига, будут выбраны объекты в списке или сетке. Так же применимо для отображения в панели приложения команд, соответствующих выбранным объектам. |
Два или большее количество пальцев касаются экрана и сдвигаются или раздвигаются.![]() |
Сжатие и растяжение для изменения масштаба. Выглядят как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd), но приложения могут использовать CSS-стили - ms-content-zooming: zoom и -ms-touch-action:
pinch-zoom для автоматической активации изменения масштаба с помощью жестов.
|
Можно использовать для оптического изменения масштаба или изменения размера, а так же, там где это применимо, для семантического масштабирования |
Два или большее количество пальцев касаются экрана и перемещаются по дуге по часовой стрелке или против часовой стрелки.![]() |
Поворот для вращения. Выглядят как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd). |
Вращение объектов или окна просмотра. |
![]() |
Скольжение пальцем от верхнего или нижнего края экрана для отображения команд приложения. Автоматически обрабатывается элементом управления AppBar, хотя приложение так же может определять это событие напрямую, посредством Windows.UI.Input.EdgeGesture |
Нижняя панель приложения содержит команды приложения для текущей страницы. Верхняя панель приложения, если это применимо, используется для команд навигации. |
![]() |
Скольжение от края для вывода системных команд. Обрабатывается системой автоматически, приложение принимает события, связанные с активированной чудо-кнопкой, когда применимо, так же события focus и blur, если меняется приложение переднего плана при скольжении от левого края. |
Скольжение от правого края отображает панель чудо-кнопок. Скльжение от левого края позволяет переключаться между запущенными приложениями. Движение пальцем от верхнего края к нижнему закрывает текущее приложение. Скользящее движение пальцем от верхнего края экрана влево или вправо прикрепляет текущее приложение на соответствующей стороне экрана. |
Дополнительные подробности и руководства по дизайну, ориентированные на этот язык касаний можно найти в материале "Жесты, операции и взаимодействия" (http://msdn.microsoft.com/library/windows/apps/hh761498.aspx).
Вы можете заметить, что многие жесты языка касаний в вышеприведенной таблице, на самом деле, не имеют отдельного события, связанного с ними (вроде жестов сжатия или вращения), но вместо этого представлены серией жестов или событий указателя. Причина подобного заключается в том, что такие жесты, использующиеся при сенсорном взаимодействии с устройством, обычно включают в себя анимацию содержимого, к которому они относятся, анимация исполняется в ходе выполнения жеста. Жесты скольжения, например, отображают линейное перемещение объекта, который сдвигают или выделяют. Жесты сжатия и растяжения часто активно меняют масштаб содержимого (Семантическое масштабирование – исключение, но в этом случае вы просто позволяете элементу управления обработать все самостоятельно). Жесту вращения, совершенно определенно, следует давать визуальную обратную связь. Коротко говоря, обработка этих жестов при сенсорном взаимодействии, в особенности, подразумевает работу с сериями событий, а не работу с каким-то одним событием.
Это – одна из причин, по которой так полезно (и в плане экономии времени!) использовать встроенные элементы управления так часто, как только возможно, так как они уже обрабатывают все, что связано с жестами. Элемент управления ListView, например, содержит всю логику, относящуюся к жестам и указателям для обработки сдвигов и скольжений, вместе с обычными касаниями. Элемент управления SemanticZoom, как я говорил, реализует жесты сжатия и растяжения, отслеживая события MSPointer*. Если вы посмотрите исходный код этого элемента управления в WinJS, вы оцените, как много он делает для вас (и увидите, на что похожа реализация функционального пользовательского элемента управления своими силами с использованием средства распознавания жестов!).
Так же вы можете обезопасить себя от множества проблем, используя CSS-свойства –ms-touch-action, описанное в разделе "CSS-стили, влияющие на ввод информации". Использование этого свойства добавляет преимущество в виде обработки операций сенсорного ввода в потоке, отличном от потока пользовательского интерфейса, таким образом, предоставляя возможность более плавной манипуляции объектами, чем при использовании обработки событий указателя или жестов.
Продолжая тему: "Дизайн приложений, использующих мышь, касания, перо – без дополнительных усилий", все эти жесты имеют эквиваленты для мыши и клавиатуры, которые так же реализованы во встроенных элементах управления. Эти эквиваленты так же полезно знать, они приведены ниже, в таблице. Раздел "Стандартные сочетания клавиш" ниже в этой лекции так же содержит много сочетаний клавиш, соответствующих командам.
| Жест | Клавиатура | Мышь | Ручка / перо |
|---|---|---|---|
| Нажатие и удерживание (или касание выделенного текста) | Клавиша вызова контекстного меню | Щелчок правой кнопкой | Нажатие и удержание |
| Касание | Клавиша Enter | Щелчок левой кнопкой | Касание |
| Скользящее движение (на короткое расстояние) | Клавиши-стрелки | Щелчок левой кнопкой и протягивание, щелчок по свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, использование колесика мыши. | Касание кнопок полосы прокрутки, перетаскивание ползунка полосы прокрутки, касание и перетаскивание |
| Скользящее движение с инерцией | Клавиши Page Up / Page Down | Щелчок левой кнопкой и протягивание, щелчок по свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, использование колесика мыши. | Касание свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, касание и перетаскивание |
| Скольжение для выделения | Клавиша пробела | Щелчок правой кнопкой | Прикосновение и протягивание |
| Сжатие / растяжение | Сочетание клавиш Ctrl + "+" и Ctrl + "-" | Клавиша Ctrl + колесико мыши или команда пользовательского интерфейса | Команда пользовательского интерфейса или аппаратная возможность устройства ввода |
| Скольжение от края | Win+Z, Win+Tab, Win+C или Win+Shift+C | Щелчки по краям экрана. Щелчок правой кнопки мыши открывает панель приложения | Протягивание внутрь от края экрана |
| Вращение | Ctrl+ "," и Ctrl+ "." | Ctrl + Shift + колесико мыши | Команда пользовательского интерфейса или аппаратная возможность устройства ввода |
Вы могли заметить бросающееся в глаза отсутствие двойного щелчка или жеста двойного касания в этом списке. Это вас удивило? В ранних релизах Windows 8 присутствовал жест двойного касания, но он оказался не особо полезным, конфликтуя с жестом масштабирования, и иногда пользователям было очень трудно выполнить его. Я могу сказать, после многих лет наблюдений за друзьями, что двойной щелчок мыши не всегда так уж полезен. Люди с не совсем устойчивыми руками часто немного перемещают мышь между щелчками, так же они могут слегка переместить пальцы в промежутках между касаниями. В результате, надежность двойного касания невысока, и так как в нем не было особой необходимости, этот жест был полностью исключен из языка касаний.
В то время, как язык касаний Windows 8 предоставляет простой, хотя и охватывающий подавляющее большинство нужд, набор жестов, не слишком сложно представить другие возможности. Вопрос заключается в том, когда целесообразно вводить новый вид жестов или манипуляций?
Во-первых, имеет смысл то, что приложения обычно не предоставляют новых способов выполнения тех же задач, например, дополнительных жестов для реализации скольжения, масштабирования. Лучше просто подойти творчески к тому, как приложение интерпретирует существующие жесты. Например, жест скольжения может сдвигать прокручиваемую область, но так же может перемещать объекты по экрану – в таком случае не нужно изобретать новый жест.
Во-вторых, если у вас имеется элемент управления, помещенный на экране там, где вам нужно организовать взаимодействие с пользователем, о жестах не нужно думать вовсе, достаточно соответствующим образом обработать данные ввода, полученные от элемента управления.
В-третьих, даже если вы полагаете, что пользовательские жесты нужны, итоговая рекомендация заключается в том, чтобы сделать взаимодействие естественным, вместо реализации того, что вы придумали только ради того, чтобы это придумать. Мы так же рекомендуем, чтобы жесты вели себя единообразно с различными указателями, использовали одинаковые скоростные и временные параметры, и так далее. Например, разделение элемента на три части тремя пальцами путем растягивания и разделение на две части двумя пальцами работает нормально, а вот если растягивание тремя пальцами увеличивает элемент, а растягивание двумя – меняет масштаб отображения – это уже плохая идея, так как она не понятна интуитивно. Похожим образом, скорость вертикального или горизонтального жеста перелистывания (flick) может воздействовать на скорость перемещения элемента, но использование быстрого жеста перелистывания для перехода на другую страницу, а медленного – для выделения текста – плохая идея. В данном случае различные функции, привязанные к скорости, усложняют пользовательский интерфейс, так как у каждого пользователя свое понимание понятий "быстро" и "медленно" и скорость жеста может быть ограничена их физическими возможностями.
И, наконец, используя любой пользовательский жест, приводит к потенциальной неоднородности между приложениями. Когда пользователь начинает работать с каким-либо приложением новым способом, он может ожидать подобного поведения от других приложений и может смутиться (или расстроиться), если эти приложения не ведут себя таким образом, особенно, если эти приложения используют похожие жесты для совершенно разных целей. Комплексные жесты, так же, могут быть сложными для некоторых, если не для многих, пользователей. Сложность жестов может быть ограничена аппаратным обеспечением устройства (количеством поддерживаемых точек касания, скоростью реакции и так далее), и обычно такие жесты сложнее обнаружить, они не понятны интуитивно. В большинстве случаев, для достижения тех же целей, возможно, проще добавить команду панели приложения, или кнопку на полотне приложения.
Как мы видели в лекции 1, вам не нужно делать ничего особенного, чтобы появлялись верхняя и нижняя панели приложения: Windows автоматически обрабатывает скольжение от верхнего и нижнего краев, как и щелчок правой кнопкой мыши, сочетание клавиш Win+Z, нажатие клавиши контекстного меню на клавиатуре. Тем не менее, вы можете обнаружить, когда именно происходят эти события, прослушивая события
var edgeGesture = Windows.UI.Input.EdgeGesture.getForCurrentView();
edgeGesture.addEventListener("starting", onStarting);
edgeGesture.addEventListener("completed", onCompleted);
edgeGesture.addEventListener("canceled", onCanceled);
Cобытие completed вызывается для всех типов ввода. События starting и canceled происходят только для сенсорных жестов. В этих событиях, свойство eventArgs.kind содержит значение из перечисления EdgeGestureKind, которое указывает на вид ввода данных, который вызвал событие. События starting и canceled всегда имеют вид touch, очевидно, в то время, как comleted может иметь вид touch, keyboard или mouse:
function onCompleted(e) {
// Определяет, было ли это событие инициировано мышью, клавиатурой или касанием
if (e.kind === Windows.UI.Input.EdgeGestureKind.touch) {
id("ScenarioOutput").innerText = "Invoked with touch.";
}
else if (e.kind === Windows.UI.Input.EdgeGestureKind.mouse) {
id("ScenarioOutput").innerText = "Invoked with right-click.";
}
else if (e.kind === Windows.UI.Input.EdgeGestureKind.keyboard) {
id("ScenarioOutput").innerText = "Invoked with keyboard.";
}
}
Этот код был взят из Сценария 1 примера "Инициация жестов у края экрана" (http://code.msdn.microsoft.com/windowsapps/Edge-gesture-invocation-76a474dd). В Сценарии 2 пример показывает, как вы можете предотвратить выполнение событий жестов у края для конкретного элемента, если вы обработаете событие contextmenu для этого элемента и вызовите eventArgs.preventDefault в вашем обработчике. Подобное делает это для одного элемента на экране, в итоге щелчок правой кнопкой мыши по элементу или нажатие клавиши контекстного меню, когда элемент имеет фокус ввода, предотвратит события жестов у края:
document.getElementById("handleContextMenuDiv").
addEventListener("contextmenu", onContextMenu);
function onContextMenu(e) {
e.preventDefault();
id("ScenarioOutput").innerText =
"The ContextMenu event was handled. The EdgeGesture event will not fire.";
}
Обратите внимание на то, что этот метод не подействует на жесты у края, выполняемые путем касания и на сочетание клавиш Win+Z, которое обычно активирует панель приложения. Это, в основном, для того, чтобы показать, что если вам нужно обработать именно событие contextmenu, вам обычно нужно предотвратить обработку жестов у края.
Во время разговора о вводе данных самое время упомянуть о множестве CSS-стилей, которые могут влиять на ввод данных в приложение.
none – деактивирует прямое выделение, хотя элемент, в целом, может быть выделен, если его элемент-родитель может быть выделен.inherit – устанавливает поведение выделения элемента таким же, как у элемента-родителя.text – активирует возможность выделения текста, даже если элемент-родитель установлен в none.element – активирует возможность выделения для произвольного элеменнта.auto – значение по умолчанию, может либо активировать возможность выделения, либо нет, в зависимости от типа элемента управления и стилизации элемента-родителя. Для элементов управления, не являющихся текстовыми элементами и не имеющими установки contenteditable="true", возможность выделения не активируется, несмотря на то, что они содержатся в элементе-родителе, который может быть выделен.Если вы хотите поэкспериментировать с различными вариантами, обратитесь к примеру "Невыделяемые области содержимого с CSS-атрибутом –ms-user-select" ( http://code.msdn.microsoft.com/windowsapps/Unselectable-content-areas-963eccd9), которому я присуждаю приз за самое длинное название JavaScript-примера во всем Windows SDK!
Связанный стиль, но не показанный в примере – это –ms-touch-select, который может принимать находиться в состоянии none или grippers, последнее – это стиль, который включает выделение с помощью маркеров в виде окружностей для сенсорного взаимодействия:
Выделяемые текстовые элементы автоматически получают этот стиль, как и другие текстовые элементы с contenteditable = "true". Вы можете использовать –ms-touch-select для того, чтобы выключить эту возможность. Для того, чтобы увидеть его действие, попробуйте это с некоторыми элементами в Сценарии 1 вышеупомянутого примера с по-настоящему длинным именем!
В лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript" мы говорили об использовании точек прикрепления для сдвига, с использованием стилей ), используются для масштабирования содержимого, такие, как ).
И, наконец, стиль –ms-touch-action предоставляет элементу множествоdouble-tap-zoom не поддерживается приложениями для Магазина Windows.
none – отключает возможность сенсорного взаимодействия с элементом.auto – активирует обычное сенсорное поведение.pan-x / pan-y – элементу разрешен горизонтальный / вертикальный сдвиг, что выполняется на ближайшем элементе-предке, который поддерживает возможности горизонтальной / вертикальной прокрутки, на таком, как родительский div.pinch-zoom – активирует изменение масштаба с помощью сведения/разведения пальцев, что выполняется на ближайшем предке, имеющем –ms-content-zooming: zoom и возможность переполнения. Например, сам по себе элемент img не отреагирует на жест с подобным стилем, однако, если вы поместите его в родительский div с установленным свойством overflow, то отреагирует.manipulation – короткое имя для pan-x pan-y pinch-zoom.Для того, чтобы привести пример сдвига и изменения масштаба, попробуем создать простое приложение с разметкой, похожей на эту (используйте здесь любое изображение):
<div id="imageContainer"> <img id="image1" src="/images/flowers.jpg" /> </div>
И стилизуем контейнер следующим образом:
#imageContainer {
overflow: auto;
-ms-content-zooming:zoom;
-ms-touch-action: manipulation;
}
API WinRT в пространстве имен ) предоставляют всю необходимую информацию о возможностях по вводу данных, присутствующих на текущем устройстве, в частности, посредством этих трех объектов:
) имеет свойства mousePresent (0 или 1), horizontalWheelPresent (0 или 1), verticalWheelPresent (0 или 1), numberOfButtons (число), и swapButtons (0 или 1).
) содержит лишь одно свойство: keyboardPresent (0 или 1). Обратите внимание, что это свойство не отражает присутствия экранной клавиатуры, которая всегда доступна. Свойство этого объекта указывает на физическое устройство – клавиатуру.
) имеет свойства ), которое позволяет узнать о направлении пользовательского интерфейса, о том, правша пользователь или левша.
Для проверки доступности сенсорных возможностей, таким образом, вы можете использовать такой код:
var tc = new Windows.Devices.Input.TouchCapabilities();
var touchPoints = 0;
if (tc.touchPresent) {
touchPoints = tc.contacts;
}
Примечание. В веб-контексте, где WinRT недоступна, некоторые данные о возможностях по вводу данных могут быть получены с помощью свойств элементов DOM ), ), и ). Это так же работает в локальном контексте.
Вы могли заметить, что возможности, перечисленные выше, ничего не сообщают о пере или ручке. Для них, а так же для более подробной информации обо всех устройствах для работы с указателями, включая сенсорный экран и мышь, у нас есть метод ), каждый из которых имеет следующие свойства:
touch, pen, или mouse.maxContacts – максимальное количество контактных точек, которое может поддерживать устройство. Обычно 1 для мыши и пера, и любое другое количество для сенсорного экрана.isIntegrated – значение true говорит о том, что устройство ввода встроено в компьютер, то есть на его присутствие можно рассчитывать. Значение false указывает на периферийное устройство, которое может отключить пользователь.physicalDeviceRect – этот объект типа Windows.Foundation.Rect предоставляет ограничивающий прямоугольник, в виде которого устройство воспринимает свою рабочую поверхность. Часто разрешение ввода сенсорного экрана не совпадает с экранными пикселями, что означает, что устройство ввода не способно выделить в точности один пиксель. Один из моих ноутбуков с сенсорным экраном, например, показывает это разрешение как 968x548 для экрана разрешением 1366x768 пикселей (как сообщает screenRect ниже). Рабочая поверхность мыши, с другой стороны, обычно один в один совпадает с экранным разрешением. Это может быть важно для приложений для рисования, которые работают с пером, если разрешение ввода меньше, чем разрешение экрана, это может означать некоторую неточность при переводе координат ввода данных в экранные пиксели.screenRect – этот объект типа Windows.Foundation.Rect предоставляет ограничивающий прямоугольник для экрана устройства, то есть, минимальные и максимальные координаты, на которые вам следует рассчитывать, обрабатывая события устройства. Этот прямоугольник принимает в расчет системы с несколькими мониторами, и он подстраивается под масштабирование разрешения.Пример "Ввод данных: возможности устройств" (http://code.msdn.microsoft.com/windowsapps/Input-device-capabilities-31b67745) в Windows SDK получает эту информацию и выводит ее на экран посредством кода в js/pointer.js. Я не привожу здесь этот код, так как все, что он делает – это обходит массив, создает длинную HTML-строку и помещает ее в DOM. В имитаторе выходные данные выглядят следующим образом. Обратите внимание на то, что имитатор, в данном случае, сообщает о наличии мыши и сенсорного экрана.
Любопытная фальсификация? Интересно то, что я запустил этот пример в отладчике Visual Studio на локальном компьютере, на ноутбуке, который совершенно определенно не имеет сенсорного экрана, но о наличии сенсорного устройства ввода, все равно, сообщалось, как на вышеприведенном изображении. Почему? Потому, что все еще был запущен имитатор Visual Studio, который добавляет виртуальное сенсорное устройство к аппаратному профилю. После того, как симулятор был полностью закрыт (а не только свернут в значок), я получил точные сведения о возможностях моего ноутбука. Так что помните об этом, если вы пишете программный код для проверки конкретных возможностей.
Пробовали удаленную отладку? Говоря об отладке, как упомянуто во врезке в лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", тестирование приложений на устройствах с разными возможностями – это отличная возможность для применения удаленной отладки в Visual Studio. Если вы еще не сделали этого, сделайте, все настойки займут лишь несколько минут. Для того, чтобы узнать подробности, обратитесь к материалу "Выполнение приложений для Магазина Windows на удаленном компьютере" (http://msdn.microsoft.com/library/windows/apps/hh441469%28v=vs.110%29.aspx).
В любой ситуации, когда вы хотите напрямую работать с сенсорным экраном, мышью или пером, возможно, для реализации части языка касаний подобным образом, используйте события MSPointer*. Большинство приложений для рисования или художественной обработки изображений, например, используют эти события для отслеживания и отображения на экране результатов взаимодействия с пользователем. Снова напомню, что указатель – это способ для рассмотрения ввода данных, имеющий более низкий уровень, чем жесты, что мы увидим в следующем разделе. Какие модели ввода данных вы испоьзуете, зависит от типа событий, с которыми вы хотите работать.
Совет. События указателей не вызываются, если система пытается выполнить манипуляцию наподобие сдвига или масштабирования. Для того чтобы отключить у элемента манипуляции, задайте -ms-content-zooming: none или -ms-touch-action: none, и избегайте использования стилей -ms-touch-action в pan-x, pan-y, pinch-zoom, и manipulation.
Как и в слудчае с другими событиями, вы можете прослушивать события MSPointer* для любых подходящих элементов, помня, опять же, что эти события транслируются в традиционные события мыши, поэтому не следует прослушивать и те и другие. Специальные события, которые описаны ниже, даны в порядке их типичной последовательности:
msReleasePointerCapture.) Обратите внимание на то, что если указатель был перемещен за пределы элемента и освобожден, элемент получит событие MSPointerOut, но не MSPointerUp.Это – те имена, которые используют с addEventListener. Эквивалентные имена свойств имеют, как обычно, форму onmspointerdown. Должно быть очевидным то, что некоторые из этих событий могут не вызываться указателями всех типов. Сенсорные экраны, например, обычно не вызывают события зависания указателя над элементом, хотя некоторые из них, те, что могут определять близость пальца, способны на это.
Совет. Если по каким-то причинам вы хотите предотвратить трансляцию события MSPointer* в традиционное событие мыши, вызовите метод eventArgs.preventDefault внутри соответствующего обработчика события.
Упражнение PointerEvents, которое можно найти среди дополнительной информации к курсу, как показано на рис. 3.1., позволяет вам увидеть, что происходит с событиями мыши, указателей, жестов, выборочно показывая группы событий на экране.
(рис 3.1) Экран упражнения PointerEvents (экран слегка обрезан для показа подробностей)
Внутри обработчиков для всех событий MSPointer*, объект eventArgs содержит полный набор свойств. Одно из них, pointerType, идентифицирует тип устройства ввода: серсорная панель (2), ручка (3), и мышь (4). Эти свойства позволяют вам, если нужно, реализовывать различное поведение для различных способов ввода. Каждый объект события так же содержит укникальное значение pointerId, которое содержит информацию о штрихе или линии для конкретной точки контакта, что позволяет согласовывать первоначальное событие MSPointerDown с последующими событиями. Когда мы взглянем, в следующем разделе, на жесты, мы так же увидим, как ипользовать pointerId события MSPointerDown для сопоставления жеста с указателем.
Полный набор свойств, который поступает вместе с событием, на самом деле, слишком велик, чтобы его здесь приводить, так как он содержит множество обычных свойств DOM (http://msdn.microsoft.com/library/windows/apps/hh831236.aspx) вместе со свойствами, имеющими отношение к указателю, из объекта типа ). Лучший способ посмотреть, что там находится – это запустить какой-нибудь код, наподобие примера "Ввод данных: обработка события указателя DOM" (http://code.msdn.microsoft.com/windowsapps/Input-DOM-pointer-and-2e5697ed) (это – приложение для рисования на элементе управления canvas), установить точку останова внутри обработчика одного из событий, и посмотреть на объект события. Нижеприведенная таблица описывает некоторые из свойсвт (и несколько методов), имеющих отношение к нашей беседе.
| Свойства | Описание |
|---|---|
currentPoint |
Объект типа ) . Он содержит множество других свойств, таких, как pointerDevice (объект Windows.Input.Device.PointerDevice как онисано ранее в этой лекции) и свойство, имеющее название properties, являющееся объектом типа Windows.UI.Input.PointerPointProperties. |
pointerType |
Источником события может быть сенсорная панель, перо или мышь: MSPOINTER_TYPE_TOUCH (2), MSPOINTER_TYPE_PEN (3), and MSPOINTER_TYPE_MOUSE (4). Вы можете использовать это, если необходимы различные действия в зависимости от типа устройства ввода. |
pointerId |
Уникальный идентификатор контакта. Он остается тем же самым в течение времени существования указателя. Если нужно, вы можете вызвать ) с этим идинтификатором для получения объекта PointerDevice (http://msdn.microsoft.com/library/windows/apps/windows.devices.input.pointerdevice.aspx), который описывает возможности устройства ввода, как описано выше в данной лекции. |
type |
Имя события, как, например, "MSPointerDown". |
x, screenX, y, screenY |
Координаты X и Y центральной точки указателя, спозиционированные относительно экрана. |
clientX, clientY |
Координаты X и Y центральной точки указателя, спозиционированные относительно пользовательской области приложения. |
offsetX, offsetY |
Координаты X и Y центральной точки указателя, спозиционированные относительно элемента. |
button |
Определяет кнопку, нажатую пользователем (на мыши или другом устройстве ввода с кнопками). Левой кнопке соответствует значение 0, средней – 1, правой – 2. Эти значения могут комбинироваться с помощью побитовой операции OR для одновременного нажатия нескольких кнопок (chord). |
ctrlKey, altKey, shiftKey |
Показывает, была ли нажата определенная клавиша клавиатуры, когда произошло событие указателя. |
hwTimestamp |
Отметка времени (в микросекундах), показывающая время, когда событие было получено от устройства. |
relatedTarget |
Предоставляет элемент, соответствующий текущему событию
Provides the element related to the current event, например, событие MSPointerOut. Предоставляет элемент, к которому было осуществлено перемещение точки касания. Может иметь значение null.
|
isPrimary |
Показывает, является ли данный указатель основным в сценарии с несколькими касания (как указатель мыши). |
| Свойства, присутствующие в зависимости от поддержки устройством (если поддержки нет, будут иметь значение 0) | |
width, height |
Ширина контактной точки и высота, заданная pointerId. |
pressure |
Нажим ручки, нормализованное к диапазону значений 0 – 255. |
rotation |
Движение курсора по часовой стрелке вокруг собственной основной оси в диапазоне 0 – 359. |
tiltX |
Наклон влево-вправо от нормального положения датчика (обычно – от перпендикуляра к поверхности), значение в диапазоне от -90 (влево), до 90 (вправо). |
tiltY |
Наклон вперед-назад от нормального положения датчика (обычно – от перпендикуляра к поверхности) в диапазоне от -10 (вперед, от пользователя), до 90 (назад, к пользователю). |
| Методы | |
currentPoint, getCurrentPoint |
Предоставляет объект типа ) для текущего указателя ввода, соответствующее целевому элементу (currentPoint) или заданному элементу (getCurrentPoint) |
intermediatePoints,getIntermediatPoints |
Предоставляет историю PointerPoint для текущего указателя по отношению к целевому элементу (intermediatePoint) или заданному элементу (getIntermediatePoints) |
Весьма поучительно запустить вышеупомянутый пример на устройстве, поддерживающем несколько одновременных касаний, так как раздельная обработка каждого pointerId позволяет вам рисовать несколькими пальцами одновременно.
Обычно, при событиях касания и поднятия указателя, устанавливают или снимают захват указателя элементом. Доступны следующие методы для поддержки этих действий каждым элементом DOM. Они применимы к каждому конкретному pointerId.
| Метод | Описание |
|---|---|
msSetPointerCapture |
Захватывает pointerId для элемента, таким образом, события указателя поступают к этому элементу и не вызываются для других элементов (даже если указатель мыши находится вне этого элемента, внутри другого). MSGotPointerCapture так же будет вызвано для элемента. |
msReleasePointerCapture |
Прекращает захват, вызывает событие MSLostPointerCapture . |
msGetPointerCapture |
Возвращает элемент, захвативший указатель, если таковой имеется (в противном случае возвращает null). |
Мы можем увидеть в примере "Ввод данных: обработка события указателя DOM", где устанавливается захват указателя в событии MSPointerDown и указатель освобождается в событии MSPointerUp:
this.MSPointerDown = function (evt) {
canvas.msSetPointerCapture(evt.pointerId);
// ...
};
this.MSPointerUp = function (evt) {
canvas.msReleasePointerCapture(evt.pointerId);
// ...
};
Первое, что стоит узнать о событиях MSGesture*, это то, что они не вызываются автоматически, как события click и MSPointer*, и недостаточно просто добавить прослушиватель и завершить тем дело (как для click!). Вместо этого вам нужно выполнить некоторые настройки, которые сообщат системе, как именно должны происходить жесты, и вам нужно исползовать MSPointerDown для того, чтобы связать настройки жеста с конкретным PointerId. Это усложняет схему работы, делая возможным работу приложения с несколькими различными жестами, независимую их обработку, что похоже на то, как работают с событиями указателей. Представьте, например, приложение-головоломку (в некоторой мере оно представлено в одном из примеров "Примеры жестов" ниже), которое позволяет нескольким пользователям сидеть вокруг сенсорного экрана размером со стол и каждому из них работать с отдельной частью головоломки. Используя жесты, каждый из игроков может управлять отдельной частью (или двумя!), перемещать ее, вращать, возможно масштабировать для того, чтобы увидеть ее покрупнее, и, конечно, пробовать поместить кусок головоломки в нужное место. Для приложений Магазина Windows, написанных на JavaScript, полезно то, что приращения манипуляции для сконфигурированных элементов – для переноса, вращения и масштабирования – даются в координатном пространстве родительского элемента, что означает, что довольно просто перенести манипуляции в CSS-трансформации и таким образом сделать манипуляции видимыми. Коротко говоря, это означает большую гибкость там, где она нужна вам. Если вам это не нужно, вы можете использовать жесты простейшим способом. Посмотрим, как все это работает.
Первый шаг к приему событий жестов заключается в создании объекта ) и в связывании его с элементом, для которого вы хотите принимать события. В упражнении PointerEvents этому элементу дано имя divElement, вам нужно сохранить этот элемент в свойстве жеста target и сохранить объект жеста в свойстве элемента gestureObject для использования его событием MSPointerDown:
var gestureObject = new MSGesture(); gestureObject.target = divElement; divElement.gestureObject = gestureObject;
Установив эти связи, вы затем можете добавить прослушиватель события, как обычно. Пример кпоказывает полный набор из шести событий жестов:
divElement.addEventListener("MSGestureTap", gestureTap);
divElement.addEventListener("MSGestureHold", gestureHold);
divElement.addEventListener("MSGestureStart", gestureStart);
divElement.addEventListener("MSGestureChange", gestureChange);
divElement.addEventListener("MSGestureEnd", gestureEnd);
divElement.addEventListener("MSInertiaStart", inertiaStart);
Однако сейчас работа еще не завершена. Если это все, что вы сделаете в своем коде, вы еще не получите этих событий, так как каждый жест нужно связать с указателем. Это делается в обработчике события MSPointerDown:
function pointerDown(e) {
//Связываем данный указатель с целевым жестом
e.target.gestureObject.addPointer(e.pointerId);
}
Для того чтобы получить возможность выполнять жесты вращения и изменения масштабирования с помощью колеса мыши (а это следует сделать), добавьте обработчик для события wheel, установите pointerId для этого события в 1 (фиксированное значение для колесика мыши) и отправьте то, что получилось в ваш обработчик MSPointerDown:
divElement.addEventListener("wheel", function (e) {
e.pointerId = 1; // Фиксированный pointerId для MouseWheel
pointerDown(e);
});
Теперь события жестов готовы к поступлению в данный элемент. (Помните, что события колесика мыши, сами по себе, транслируются, Ctrl+колесо мыши – это масштабирование, Shift+Ctrl+колесо мыши – вращение). Более того, если возникнет дополнительное событие MSPointerDown для того же самого элемента с различными значениями pointerId, метод addPointer включит этот новый указатель в жест. Это автоматически активирует жесты изменения масштаба и вращения, которые основаны на нескольких точках касания.
Если вы запустите упражнение PointerEvents (установив флаги Ignore Mouse Events (Игнорировать события мыши) и Ignore Pointer Events (Игнорировать события указателя)), и начнете касаться экрана, касаться, удерживая палец на экране, выполнять касание и короткое перетаскивание (с помощью сенсорного экрана или мыши), вы увидите выходные данные, похожие на те, что приведены на рис.3.2
(рис 3.2) Упражнение PointerEvents, выходные данные для событий жестов (скриншот слегка обрезан для выделения деталей)
Снова хочу отметить, что события жестов вызываются в ответ на последовательность событий указателя, предлагая высокоуровневую интерпретацию низкоуровневых событий указателя. В процессе интерпретации происходит дифференцирование событий касания/удержания от событий начала/изменения/окончания, выясняется, как и когда началось событие MSInertiaStart, и что предпринимает распознаватель жестов, когда объекту MSGesture передаются несколько точек.
Начиная с жеста одного указателя, первый аспект дифференцирования – это порог перемещения указателя (pointer movement threshold). Когда распознаватель жестов обнаруживает событие MSPointerDown, он начинает наблюдать за событиями MSPointerMove для того, чтобы видеть, остаются ли они внутри порогового расстояния, которое является эффективной границей для событий касания и удерживания. Это предназначено для того, чтобы игнорировать небольшое дрожание мыши или точки касания, как показано на рисунке ниже (я бы сказал, что здесь это несколько преувеличено!), когда происходит касание, небольшое перемещение, после чего указатель поднимается, генерируется событие MSGestureTap:
Horizontal threshold (Горизонтальный порог перемещения)
Vertical threschold (Вертикальный порог перемещения)
Many events (Множество событий)
Различить события MSGestureTap и MSGestureHold позволяет временной порог (time threshold):
MSGestureTap происходит, когда за событием MSPointerDown следует событие MSPointerUp в пределах временного порога.
MSGestureHold происходит, когда за событием MSPointerDown следует событие MSPointerUp с превышением временного порога. В подобном случае, один раз, при пересечении временного порога, вызывается событие MSGestureHold с eventArgs.detail установленным в 1 (MSGESTURE_FLAG_BEGIN). При условии, что указатель все еще находится в пределах порога перемещения, событие MSGestureHold вызывается еще раз, когда происходит MSPointerUp, с eventArgs.detail установленным в 2 (MSGESTURE_FLAG_END). Вы можете увидеть эти детали в двух первых событиях на рис. 3.2. выше.
Флаги жестов в значении eventArgs.detail сопровождаются множеством других свойств, касающихся расположения и перемещения в объекте eventArgs, как показано в следующей таблице:
| Свойства | Описание |
|---|---|
screenX, screenY |
Координаты X и Y центральной точки жеста, спозиционированные |
clientX, clientY |
Координаты X и Y центральной точки жеста, спозиционированные относительно пользовательской области приожения. |
offsetX, offsetY |
Координаты X и Y центральной точки жеста, спозиционированные |
translationX,
translationY
|
Перенос по осям X и Y. |
velocityX,
velocityY
|
Скорость перемещения по осям X и Y. |
scale |
Коэффициент масштабирования (процентное изменение масштаба). |
expansion |
Скорость расширения области манипуляции. |
rotation |
Угол поворота в радианах. |
velocityAngular |
Угловая скорость в радианах. |
detail |
Содержит флаги жеста, которые описывают состояние события жеста. Эти флаги определены как значения в eventArgs:
eventArgs.MSGESTURE_FLAG_NONE (0): Указывает на текущий жест, такой, как MSGestureChange где представлены изменения координат.
eventArgs.MSGESTURE_FLAG_BEGIN (1): Начало последовательности жестов. Если взаимодействие включает в себя единственное событие, такое, как MSGestureTap, и флаг MSGESTURE_FLAG_BEGIN, и флаг MSGESTURE_FLAG_END будут установлены (значение 3).eventArgs.MSGESTURE_FLAG_END (2): Конец последовательности жестов. Опять же, если взаимодействие включает в себя единственный жест, такой, как MSGestureTap, и флаг MSGESTURE_FLAG_BEGIN, и флаг MSGESTURE_FLAG_END будут установлены (значение 3).eventArgs.MSGESTURE_FLAG_CANCEL (4): Жест был отменен. |
hwTimestamp |
Отметка времени, когда указатель был назначен системой при поступлении входных данных от устройства. |
Многие из этих свойств становятся гораздо интереснее, когда указатель выходит за пределы порога перемещения, после чего уже не произойдет события касания (tap) или удерживания (hold). Вместо этого, как только указатель пересечет порог, будет выполнено событие MSGestureStart, после чего возможен вызов событий MSGestureChange, их может не быть вовсе, но обычно их довольно много. В конце вызывается одно событие MSGestureEnd:
Обратите внимание на то, что если указатель не пересечет порог перемещения достаточно долго для вызова первого MSGestureHold с флагом MSGESTURE_FLAG_BEGIN, но затем указатель переместится за пределы порога, MSGestureHold будет вызван второй раз, с флагами MSGESTURE_FLAG_CANCEL | MSGESTURE_FLAG_END в eventArgs.detail (значение 6), за ним последует MSGestureStart с флагом MSGESTURE_FLAG_BEGIN. Подобная последовательность позволяет дифференцировать событие удержания (hold) от жестов прокрутки или перетаскивания, даже если пользователь какое-то время удерживал элемент на месте.
События MSGestureStart, MSGestureChange, и MSGestureEnd все вместе задают манипуляцию (manipulation) для элемента, с которым связан жест, когда указатель контактирует с элементом в течение манипуляции. Технически это означает, что указатель больше не перемещается, когда он освобождается.
Если указатель продолжает перемещаться после того, как он освобожден, тогда мы переключаемся с манипуляции на движение по инерции (inertial motion). В этом случае вызывается событие MSInertiaStart, оно показывает, что указатель продолжает несмотря на то, что контакт с элементом потерян, или указатель поднят. В результате, вы продолжаете получать события MSGestureChange до тех пор, пока движение не будет завершено:
С концептуальной точки зрения разница между манипуляцией и движением по инерции проиллюстрирована на рис. 3.3. Кривые, показанные здесь, не обязательно отражают реальные изменения между сообщениями. Если указатель переместился вдоль зеленой линии и болше не двигается после отпускания указателя, мы видим последовательность жестов, которая описывает манипуляцию. Если указатель отпущен при движении, мы видем событие MSInertiaStart между сериями событий MSGestureChange, и последовательность событий продолжается в виде оранжевой линии.
(рис 3.3) Концептуальное представление манипуляции (зеленая линия) и движения по инерции (оранжевая линия).
Возвращаясь к рис. 3.2., где выпадающий список Show (Показ) был установлен в значение Velocity (Скорость), выходные данные для событий MSGestureChange включали значения eventArgs.velocity*. В течение манипуляции, скорость может меняться с любой частотой, в зависимости от того, как движется указатель. Однако когда начинается движение по инерции, скорость постепенно падает до нуля, и тогда происходит событие MSGestureEnded. Количество событий изменения зависит от того, сколько времени нужно для того, чтобы продолжать замедляющееся, вплоть до остановки, движение, но если вы просто перемещаете элемент по экрану с помощью этих событий, несущих информацию об изменениях, пользователь увидит приятную плавную анимацию. Вы можете поэкспериментировать с этим в упражнении PointerEvents, используя выпадающий список Show для того, чтобы посмотреть, как на другие свойства позиционирования влияют различные жесты при манипуляциях и движении по инерции.
Файлы к данной лекции Вы можете скачать здесь.
Сенсорный экран, безусловно, это одно из самых замечательных средств взаимодействия с компьютером, которое в наши дни, наконец, повзрослело. Конечно, уже много лет у нас есть устройства, которыми можно управлять касаниями. Помню, я работал с экраном, чувствительным к касаниям, в колледже, должен признать, это было до неприличия давно. Тогда сенсорный датчик представлял собой набор прозрачных проводников, встроенных в лист пластика, расположенный над экраном, с общим сенсорным разрешением что-то около 60 точек в ширину и 40 в высоту… и, что действительно выдает давность этих событий, монитор представлял собой полностью текстовый терминал.
К счастью, в последние годы сенсорные экраны чрезвычайно развились. Они достаточно чувствительны для нужд общего назначения (вам не нужно бить по ним, чтобы они зафиксировали событие ввода данных), они встроены в дисплеи высокого разрешения, они сравнительно дешевы, и они могут деть гораздо больше, чем копировать поведение мыши, а именно – они поддерживают множество одновременных касаний и сложные жесты.
Хорошие возможности по сенсорному взаимодействию – это фундаментальная функция отличных приложений, и разработка для сенсорного взаимодействия означает, во многом, переосмысление пользовательского интерфейса. В наших макетах, например, это предусматривает создание целей касания, размер которых подходит для пальцев различного размера. В плане перемещения по содержимому, это подразумевает использование прямых жестов, таких, как протягивание и жесты сжатия и разведения пальцев, вместо того, чтобы полагаться только на выделение элементов и элементы управления для навигации. Аналогично, разработка для сенсорного взаимодействия подразумевает размышление о том, как жесты могут обогатить опыт взаимодействия пользователя и приложения, и так же, как обеспечить возможности по исследованию элементов и обратную связь пользователям, которые привыкли полагаться лишь на события мыши, наподобие зависания указателя над объектом.
В целом, подходите к дизайну так, будто сенсорное взаимодействие – это единственный способ, который есть у пользователя. В то же время, важно помнить, что новые способы ввода редко полностью замещают устаревшие. Конечно, перфокарты, в конечном счете, исчезли, но изобретение мыши не сделало ненужной клавиатуру. Доступность распознавания речи или рукописного ввода не привели к исчезновению мыши и клавиатуры. Я думаю, то же самое справедливо для сенсорного взаимодействия: это дополнительный способ ввода, который имеет собственные особенные преимущества, но вряд ли он полностью вытеснит другие. Как сказал Билл Бакстон из Microsoft Research: "Каждое отдельное явление, включая сенсорное взаимодействие, хорошо подходит для чего-то одного и плохо – для чего-то другого". Я надеюсь, со временем, мы будем использовать клавиатуру, мышь, и сенсорный экран вместе, так же, как мы научились использовать в повседневной работе мышь в те времена, когда единственным средство ввода информации была клавиатура.
Windows спроектирована для хорошей работы со всеми формами ввода – для отличной работы с сенсорным экраном, мышью, клавиатурой, и все это – на разном аппаратном обеспечении! (И сертификация для Магазина Windows требует, чтобы все приложения обладали этими возможностями.) По этоим причинам, Windows предоставляет унифицированную, основанную на указателе (pointer) модель, где вы можете дифференцировать различные способы ввода, если нужно, но можете обрабатывать их все равнозначно. Так же вы можете сосредоточиться на жестах высокого уровня, которые могут исходить из многих источников ввода, и совсем не беспокоиться об исходных событиях указателя. На самом деле, тот факт, что мы не поднимали до сих пор этот вопрос, показывает, как естественно можно работать со всеми видами указателей ввода и не беспокоиться о них: элементы управления и другие части пользовательского интерфейса, которые мы использовали, выполняют за нас всю подобную работу. Необходимость в обработке подобных событий возникает преимущественно при создании собственных элементов управления или для выполнения прямых манипуляций с объектами, которые не являются элементами управления.
Клавиатура – это важный инструмент для ввода данных, это относится и к аппаратной клавиатуре, и к экранной "программной" клавиатуре. Последней уделяется много внимания в наше время, в плане устройств, обладающих лишь возможностями сенсорного взаимодействия с пользователем, но, на самом деле, основные вопросы касались доступности. В Windows, так же, программная клавитура включает в себя возможности распознавания рукописного текста, иногда приложения просто включают в себя эту возможность. И когда приложение нуждается в более плотной работе с исходными данными рукописного ввода (ink), оно так же может воспользоваться этими возможностями.
Другая тема, которой мы коснемся в этой лекции, касается датчиков (сенсоров). До тех пор, пока вы не узнаете, что это за датчики, может показаться непоследовательным помещать эту тему вместе с темой о вводе данных. Датчики, вместе с сенсорным экраном – это еще один способ ввода данных. Сенсоры сообщают приложению, что происходит с устройством во внешнем мире: как оно расположено в пространстве (относительно некоторого количества опорных точек), как оно перемещается в пространстве, как оно расположено по отношению к "нормальной" ориентации, и даже то, насколько яркий свет освещает устройство. Видя сенсоры в таком свете (преднамеренный каламбур), мы начинаем видеть возможности прямой интеграции приложений с окружающим миром вместо того, чтобы нуждаться в том, что пользователь сообщит приложению о внешних условиях каким-то абстрактным способом. Хочу предупредить вас, что как только вы увидите, как легко использовать API WinRT для работы с датчиками, вам может захотеться купить новое устройство, которое хорошо ими оснащено!
Когда речь идет о вводе данных, основанном на указателе, что включает в себя ввод данных с помощью мыши, касаний, ручки и пера – особое сообщение от Microsoft имело и имеет актуальность: "Дизайн приложений, использующих мышь, касания, перо – без дополнительных усилий". Это – очень важно, как мы увидим дальше, но мы так же обнаружили, что фразы вроде "дизайн, ориентированный на касания" ("first-touch design"), хорошо звучащие для потребителей, может выглядеть пугающей для разработчиков! Когда все внимание обращено на взаимодействие с помощью касаний, нужно учитывать, что пользователи весьма требовательны в своих ожиданиях, и для соответствия продукта этим ожиданиям может потребоваться много работы.
К счастью, Windows 8 предоставляет единую платформу для обработки указателя ввода из всех источников, в итоге, вам не нужно особо задумываться об их различиях до тех пор, пока у вас не будет особых причин сделать это. Таким образом, проектирование приложений с учетом соображений дизайна, ориентированного на касания, это – больше вопрос дизайна, чем вопрос программирования.
В следующем разделе мы подробнее поговорим о проектировании приложений для сенсорного взаимодействия. Для начала мне хотелось бы обсудить, как вам, в роли разработчика, следует подходить к реализации подобного дизайна, до тех пор, пока вам не понадобится делать различия между типами указателя:
tabindex для тех пользователей, которые будут применять клавиатуру, назначьте обработчики для стандартных событий DOM, наподобие click, и все готово. Элементы управления наподобие элемента для контекстного масштабирования уже обрабатывают различные виды ввода (как мы видели в лекции 5 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript"), CSS-стили, наподобие точек прикрепления и масштабирования контента обрабатывают различные жесты взаимодействия с приложением.MsGestureTap и MsGestureHold, вместе с последовательностями событий для жестов, использующих инерцию (MSGestureStart, MSGestureChange, и MSGestureEnd). Преимущество здесь в том, что эти жесты представляют собой высокоуровневую интерпретацию низкоуровневых событий указателя, что означает, что вам не нужно выполнять подобную интерпретацию самостоятельно. Например, касание (down) с последующим отрывом, поднятием (up) указателя в пределах определенного порога передвижения (для того, чтобы учеcть шевеление пальцев) становится единым жестом касания (tap). Касание, за которым следует короткое перетаскивание (drag), после чего указатель поднимается, становится жестом прокрутки (swipe), которое вызывает последовательность
событий, возможно, включающих события, указывающие на инерцию (те, которые продолжают вызываться, даже после того, как указатель, наподобие точки касания, физически освобожден). Обратите внимание на то, что если вы хотите захватить и сохранить данные ввода указателя, не обращая внимание на жесты, есть встроенная возможность для рукописного ввода (inking), позже мы ее рассмотрим.MsPointerDown, MsPointerMove и так далее.Это – события более низкого уровня, чем события жестов, и они, преимущественно, подходят для приложений, которые не нуждаются в интерпретации жестов. Например, приложению для рисования нужно просто отследить различные указатели и отобразить их на экране, здесь концепции наподобие прокрутки и инерции значения не имеют. События указателя так же предоставляют специфическую информацию от устройств – такую, как давление, поворот, сдвиг, и они отражаются в событиях указателя. Напомню, возможно реализовать обработку жестов на основе прямой обработки событий указателя, как делает большое количество встроенных элементов управления.А что же о традиционных событиях DOM, которые мы знаем и любим, помимо )). Используйте в коде жесты и события указателя так часто, как сможете.
Примечание. Визуальная обратная связь для сенсорного ввода – это одно из требований к сертификации приложений для Windows 8 (раздел 3.5., http://msdn.microsoft.com/library/windows/apps/hh694083.aspx ), она применима везде в ваших приложениях, так же, как и к любому веб-содержимому, которые вы можете отображать в элементе iframe. Предоставление обратной связи подразумевает исполнение короткой анимации, которая подтверждает касание. Для этих целей вы можете использовать библиотеку анимаций WinJS или, напрямую, CSS-анимации и переходы, как описано в лекции 5.
Весьма обширная статья в Центре разработчиков Windows, "Проектирование взаимодействия с сенсорным экраном" (http://msdn.microsoft.com/library/windows/apps/hh465415.aspx) полезна и для дизайнеров, и для разработчиков. Она посвящена различным соображениям эргономики, содержит несколько хороших изображений, посвященных различным размерам пальцев, предоставляет четкое руководство по подходящим размерам целей касания, продиктованное реальными условиями, и описывает ключевые принципы дизайна, такие, как обеспечение прямой обратной связи для сенсорного взаимодействия (анимации) и то, как содержимое должно следовать за пальцем.
Особенно важно то, что руководство по дизайну так же описывает Язык касаний Windows 8 (Windows 8 Touch Language), который включает в себя восемь основных жестов, которые поддерживаются и системой, и элементами управления. Таблица ниже показывает и описывает эти жесты, и показывает, какие события, воспринимаемые приложением, им соответствуют.
| Жест | Значение и событие жеста | Описание |
|---|---|---|
Палец касается экрана и остается в месте касания ![]() |
Нажатие с удержанием для вывода информации. Выглядит как события элемента contextmenu и MsGestureHold. |
Этот жест предназначен для отображения подробной информации или справочного изображения (например, всплывающей подсказки или контекстного меню без необходимости выполнения действия. Все содержимое, отображаемое таким образом, не должно препятствовать сдвигу объектов пользователями, если они проводят пальцем по экрану. |
Палец касается экрана, после чего поднимается.![]() |
Касание для основного действия (для управления), выглядит как события элемента click и MSGestureTap. |
Касание элемента вызывает его основное действие, обычно – выполнение команды, установку флага, установку оценки, позиционирование курсора и так далее. |
Один или несколько пальцев касаются экрана и перемещаются в одном направлении.![]() |
Скольжение для сдвига (может быть горизонтальным или вертикальным). Выглядит как события прокрутки и как серия событий (MSGestureStart, MSGestureChange, MSGestureEnd, возможно с событиями инерционных жестов, о которых оповещает MSInertiaStart, плюс - события MSPointer*). |
Скольжение используется, главным образом, для сдвига объектов, но так же подходят для перемещений, рисования или рукописного ввода. Скольжение так же можно использовать для выбора мелких элементов, расположенных близко друг к другу. Для этого нужно выполнить жест потирания (scrubbing) (провести пальцем по связанным объектам, таким, как переключатели) |
Один или несколько пальцев касаются экрана и перемещаются на короткое расстояние в одном направлении![]() |
Скольжение для выбора, управления и перемещения (может быть вертикальным или горизонтальным), так же называется скольжением по диагонали (cross-slide), выглядит как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd, так же, как и события MSPointer*). Средство распознавания жестов, однако, не отличает этот жест от вертикального сдвига, поэтому приложение или элемент управления нуждаются в прямой реализации подобной интерпретации (хорошая причина для использования элементов управления наподобие ListView!) |
Если прочертить пальцем короткий отрезок, перпендикулярный направлению сдвига, будут выбраны объекты в списке или сетке. Так же применимо для отображения в панели приложения команд, соответствующих выбранным объектам. |
Два или большее количество пальцев касаются экрана и сдвигаются или раздвигаются.![]() |
Сжатие и растяжение для изменения масштаба. Выглядят как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd), но приложения могут использовать CSS-стили - ms-content-zooming: zoom и -ms-touch-action:
pinch-zoom для автоматической активации изменения масштаба с помощью жестов.
|
Можно использовать для оптического изменения масштаба или изменения размера, а так же, там где это применимо, для семантического масштабирования |
Два или большее количество пальцев касаются экрана и перемещаются по дуге по часовой стрелке или против часовой стрелки.![]() |
Поворот для вращения. Выглядят как серия жестов (MSGestureStart, MSGestureChange, MSGestureEnd). |
Вращение объектов или окна просмотра. |
![]() |
Скольжение пальцем от верхнего или нижнего края экрана для отображения команд приложения. Автоматически обрабатывается элементом управления AppBar, хотя приложение так же может определять это событие напрямую, посредством Windows.UI.Input.EdgeGesture |
Нижняя панель приложения содержит команды приложения для текущей страницы. Верхняя панель приложения, если это применимо, используется для команд навигации. |
![]() |
Скольжение от края для вывода системных команд. Обрабатывается системой автоматически, приложение принимает события, связанные с активированной чудо-кнопкой, когда применимо, так же события focus и blur, если меняется приложение переднего плана при скольжении от левого края. |
Скольжение от правого края отображает панель чудо-кнопок. Скльжение от левого края позволяет переключаться между запущенными приложениями. Движение пальцем от верхнего края к нижнему закрывает текущее приложение. Скользящее движение пальцем от верхнего края экрана влево или вправо прикрепляет текущее приложение на соответствующей стороне экрана. |
Дополнительные подробности и руководства по дизайну, ориентированные на этот язык касаний можно найти в материале "Жесты, операции и взаимодействия" (http://msdn.microsoft.com/library/windows/apps/hh761498.aspx).
Вы можете заметить, что многие жесты языка касаний в вышеприведенной таблице, на самом деле, не имеют отдельного события, связанного с ними (вроде жестов сжатия или вращения), но вместо этого представлены серией жестов или событий указателя. Причина подобного заключается в том, что такие жесты, использующиеся при сенсорном взаимодействии с устройством, обычно включают в себя анимацию содержимого, к которому они относятся, анимация исполняется в ходе выполнения жеста. Жесты скольжения, например, отображают линейное перемещение объекта, который сдвигают или выделяют. Жесты сжатия и растяжения часто активно меняют масштаб содержимого (Семантическое масштабирование – исключение, но в этом случае вы просто позволяете элементу управления обработать все самостоятельно). Жесту вращения, совершенно определенно, следует давать визуальную обратную связь. Коротко говоря, обработка этих жестов при сенсорном взаимодействии, в особенности, подразумевает работу с сериями событий, а не работу с каким-то одним событием.
Это – одна из причин, по которой так полезно (и в плане экономии времени!) использовать встроенные элементы управления так часто, как только возможно, так как они уже обрабатывают все, что связано с жестами. Элемент управления ListView, например, содержит всю логику, относящуюся к жестам и указателям для обработки сдвигов и скольжений, вместе с обычными касаниями. Элемент управления SemanticZoom, как я говорил, реализует жесты сжатия и растяжения, отслеживая события MSPointer*. Если вы посмотрите исходный код этого элемента управления в WinJS, вы оцените, как много он делает для вас (и увидите, на что похожа реализация функционального пользовательского элемента управления своими силами с использованием средства распознавания жестов!).
Так же вы можете обезопасить себя от множества проблем, используя CSS-свойства –ms-touch-action, описанное в разделе "CSS-стили, влияющие на ввод информации". Использование этого свойства добавляет преимущество в виде обработки операций сенсорного ввода в потоке, отличном от потока пользовательского интерфейса, таким образом, предоставляя возможность более плавной манипуляции объектами, чем при использовании обработки событий указателя или жестов.
Продолжая тему: "Дизайн приложений, использующих мышь, касания, перо – без дополнительных усилий", все эти жесты имеют эквиваленты для мыши и клавиатуры, которые так же реализованы во встроенных элементах управления. Эти эквиваленты так же полезно знать, они приведены ниже, в таблице. Раздел "Стандартные сочетания клавиш" ниже в этой лекции так же содержит много сочетаний клавиш, соответствующих командам.
| Жест | Клавиатура | Мышь | Ручка / перо |
|---|---|---|---|
| Нажатие и удерживание (или касание выделенного текста) | Клавиша вызова контекстного меню | Щелчок правой кнопкой | Нажатие и удержание |
| Касание | Клавиша Enter | Щелчок левой кнопкой | Касание |
| Скользящее движение (на короткое расстояние) | Клавиши-стрелки | Щелчок левой кнопкой и протягивание, щелчок по свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, использование колесика мыши. | Касание кнопок полосы прокрутки, перетаскивание ползунка полосы прокрутки, касание и перетаскивание |
| Скользящее движение с инерцией | Клавиши Page Up / Page Down | Щелчок левой кнопкой и протягивание, щелчок по свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, использование колесика мыши. | Касание свободной области полосы прокрутки, перетаскивание ползунка полосы прокрутки, касание и перетаскивание |
| Скольжение для выделения | Клавиша пробела | Щелчок правой кнопкой | Прикосновение и протягивание |
| Сжатие / растяжение | Сочетание клавиш Ctrl + "+" и Ctrl + "-" | Клавиша Ctrl + колесико мыши или команда пользовательского интерфейса | Команда пользовательского интерфейса или аппаратная возможность устройства ввода |
| Скольжение от края | Win+Z, Win+Tab, Win+C или Win+Shift+C | Щелчки по краям экрана. Щелчок правой кнопки мыши открывает панель приложения | Протягивание внутрь от края экрана |
| Вращение | Ctrl+ "," и Ctrl+ "." | Ctrl + Shift + колесико мыши | Команда пользовательского интерфейса или аппаратная возможность устройства ввода |
Вы могли заметить бросающееся в глаза отсутствие двойного щелчка или жеста двойного касания в этом списке. Это вас удивило? В ранних релизах Windows 8 присутствовал жест двойного касания, но он оказался не особо полезным, конфликтуя с жестом масштабирования, и иногда пользователям было очень трудно выполнить его. Я могу сказать, после многих лет наблюдений за друзьями, что двойной щелчок мыши не всегда так уж полезен. Люди с не совсем устойчивыми руками часто немного перемещают мышь между щелчками, так же они могут слегка переместить пальцы в промежутках между касаниями. В результате, надежность двойного касания невысока, и так как в нем не было особой необходимости, этот жест был полностью исключен из языка касаний.
В то время, как язык касаний Windows 8 предоставляет простой, хотя и охватывающий подавляющее большинство нужд, набор жестов, не слишком сложно представить другие возможности. Вопрос заключается в том, когда целесообразно вводить новый вид жестов или манипуляций?
Во-первых, имеет смысл то, что приложения обычно не предоставляют новых способов выполнения тех же задач, например, дополнительных жестов для реализации скольжения, масштабирования. Лучше просто подойти творчески к тому, как приложение интерпретирует существующие жесты. Например, жест скольжения может сдвигать прокручиваемую область, но так же может перемещать объекты по экрану – в таком случае не нужно изобретать новый жест.
Во-вторых, если у вас имеется элемент управления, помещенный на экране там, где вам нужно организовать взаимодействие с пользователем, о жестах не нужно думать вовсе, достаточно соответствующим образом обработать данные ввода, полученные от элемента управления.
В-третьих, даже если вы полагаете, что пользовательские жесты нужны, итоговая рекомендация заключается в том, чтобы сделать взаимодействие естественным, вместо реализации того, что вы придумали только ради того, чтобы это придумать. Мы так же рекомендуем, чтобы жесты вели себя единообразно с различными указателями, использовали одинаковые скоростные и временные параметры, и так далее. Например, разделение элемента на три части тремя пальцами путем растягивания и разделение на две части двумя пальцами работает нормально, а вот если растягивание тремя пальцами увеличивает элемент, а растягивание двумя – меняет масштаб отображения – это уже плохая идея, так как она не понятна интуитивно. Похожим образом, скорость вертикального или горизонтального жеста перелистывания (flick) может воздействовать на скорость перемещения элемента, но использование быстрого жеста перелистывания для перехода на другую страницу, а медленного – для выделения текста – плохая идея. В данном случае различные функции, привязанные к скорости, усложняют пользовательский интерфейс, так как у каждого пользователя свое понимание понятий "быстро" и "медленно" и скорость жеста может быть ограничена их физическими возможностями.
И, наконец, используя любой пользовательский жест, приводит к потенциальной неоднородности между приложениями. Когда пользователь начинает работать с каким-либо приложением новым способом, он может ожидать подобного поведения от других приложений и может смутиться (или расстроиться), если эти приложения не ведут себя таким образом, особенно, если эти приложения используют похожие жесты для совершенно разных целей. Комплексные жесты, так же, могут быть сложными для некоторых, если не для многих, пользователей. Сложность жестов может быть ограничена аппаратным обеспечением устройства (количеством поддерживаемых точек касания, скоростью реакции и так далее), и обычно такие жесты сложнее обнаружить, они не понятны интуитивно. В большинстве случаев, для достижения тех же целей, возможно, проще добавить команду панели приложения, или кнопку на полотне приложения.
Как мы видели в лекции 1, вам не нужно делать ничего особенного, чтобы появлялись верхняя и нижняя панели приложения: Windows автоматически обрабатывает скольжение от верхнего и нижнего краев, как и щелчок правой кнопкой мыши, сочетание клавиш Win+Z, нажатие клавиши контекстного меню на клавиатуре. Тем не менее, вы можете обнаружить, когда именно происходят эти события, прослушивая события
var edgeGesture = Windows.UI.Input.EdgeGesture.getForCurrentView();
edgeGesture.addEventListener("starting", onStarting);
edgeGesture.addEventListener("completed", onCompleted);
edgeGesture.addEventListener("canceled", onCanceled);
Cобытие completed вызывается для всех типов ввода. События starting и canceled происходят только для сенсорных жестов. В этих событиях, свойство eventArgs.kind содержит значение из перечисления EdgeGestureKind, которое указывает на вид ввода данных, который вызвал событие. События starting и canceled всегда имеют вид touch, очевидно, в то время, как comleted может иметь вид touch, keyboard или mouse:
function onCompleted(e) {
// Определяет, было ли это событие инициировано мышью, клавиатурой или касанием
if (e.kind === Windows.UI.Input.EdgeGestureKind.touch) {
id("ScenarioOutput").innerText = "Invoked with touch.";
}
else if (e.kind === Windows.UI.Input.EdgeGestureKind.mouse) {
id("ScenarioOutput").innerText = "Invoked with right-click.";
}
else if (e.kind === Windows.UI.Input.EdgeGestureKind.keyboard) {
id("ScenarioOutput").innerText = "Invoked with keyboard.";
}
}
Этот код был взят из Сценария 1 примера "Инициация жестов у края экрана" (http://code.msdn.microsoft.com/windowsapps/Edge-gesture-invocation-76a474dd). В Сценарии 2 пример показывает, как вы можете предотвратить выполнение событий жестов у края для конкретного элемента, если вы обработаете событие contextmenu для этого элемента и вызовите eventArgs.preventDefault в вашем обработчике. Подобное делает это для одного элемента на экране, в итоге щелчок правой кнопкой мыши по элементу или нажатие клавиши контекстного меню, когда элемент имеет фокус ввода, предотвратит события жестов у края:
document.getElementById("handleContextMenuDiv").
addEventListener("contextmenu", onContextMenu);
function onContextMenu(e) {
e.preventDefault();
id("ScenarioOutput").innerText =
"The ContextMenu event was handled. The EdgeGesture event will not fire.";
}
Обратите внимание на то, что этот метод не подействует на жесты у края, выполняемые путем касания и на сочетание клавиш Win+Z, которое обычно активирует панель приложения. Это, в основном, для того, чтобы показать, что если вам нужно обработать именно событие contextmenu, вам обычно нужно предотвратить обработку жестов у края.
Во время разговора о вводе данных самое время упомянуть о множестве CSS-стилей, которые могут влиять на ввод данных в приложение.
none – деактивирует прямое выделение, хотя элемент, в целом, может быть выделен, если его элемент-родитель может быть выделен.inherit – устанавливает поведение выделения элемента таким же, как у элемента-родителя.text – активирует возможность выделения текста, даже если элемент-родитель установлен в none.element – активирует возможность выделения для произвольного элеменнта.auto – значение по умолчанию, может либо активировать возможность выделения, либо нет, в зависимости от типа элемента управления и стилизации элемента-родителя. Для элементов управления, не являющихся текстовыми элементами и не имеющими установки contenteditable="true", возможность выделения не активируется, несмотря на то, что они содержатся в элементе-родителе, который может быть выделен.Если вы хотите поэкспериментировать с различными вариантами, обратитесь к примеру "Невыделяемые области содержимого с CSS-атрибутом –ms-user-select" ( http://code.msdn.microsoft.com/windowsapps/Unselectable-content-areas-963eccd9), которому я присуждаю приз за самое длинное название JavaScript-примера во всем Windows SDK!
Связанный стиль, но не показанный в примере – это –ms-touch-select, который может принимать находиться в состоянии none или grippers, последнее – это стиль, который включает выделение с помощью маркеров в виде окружностей для сенсорного взаимодействия:
Выделяемые текстовые элементы автоматически получают этот стиль, как и другие текстовые элементы с contenteditable = "true". Вы можете использовать –ms-touch-select для того, чтобы выключить эту возможность. Для того, чтобы увидеть его действие, попробуйте это с некоторыми элементами в Сценарии 1 вышеупомянутого примера с по-настоящему длинным именем!
В лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript" мы говорили об использовании точек прикрепления для сдвига, с использованием стилей ), используются для масштабирования содержимого, такие, как ).
И, наконец, стиль –ms-touch-action предоставляет элементу множествоdouble-tap-zoom не поддерживается приложениями для Магазина Windows.
none – отключает возможность сенсорного взаимодействия с элементом.auto – активирует обычное сенсорное поведение.pan-x / pan-y – элементу разрешен горизонтальный / вертикальный сдвиг, что выполняется на ближайшем элементе-предке, который поддерживает возможности горизонтальной / вертикальной прокрутки, на таком, как родительский div.pinch-zoom – активирует изменение масштаба с помощью сведения/разведения пальцев, что выполняется на ближайшем предке, имеющем –ms-content-zooming: zoom и возможность переполнения. Например, сам по себе элемент img не отреагирует на жест с подобным стилем, однако, если вы поместите его в родительский div с установленным свойством overflow, то отреагирует.manipulation – короткое имя для pan-x pan-y pinch-zoom.Для того, чтобы привести пример сдвига и изменения масштаба, попробуем создать простое приложение с разметкой, похожей на эту (используйте здесь любое изображение):
<div id="imageContainer"> <img id="image1" src="/images/flowers.jpg" /> </div>
И стилизуем контейнер следующим образом:
#imageContainer {
overflow: auto;
-ms-content-zooming:zoom;
-ms-touch-action: manipulation;
}
API WinRT в пространстве имен ) предоставляют всю необходимую информацию о возможностях по вводу данных, присутствующих на текущем устройстве, в частности, посредством этих трех объектов:
) имеет свойства mousePresent (0 или 1), horizontalWheelPresent (0 или 1), verticalWheelPresent (0 или 1), numberOfButtons (число), и swapButtons (0 или 1).
) содержит лишь одно свойство: keyboardPresent (0 или 1). Обратите внимание, что это свойство не отражает присутствия экранной клавиатуры, которая всегда доступна. Свойство этого объекта указывает на физическое устройство – клавиатуру.
) имеет свойства ), которое позволяет узнать о направлении пользовательского интерфейса, о том, правша пользователь или левша.
Для проверки доступности сенсорных возможностей, таким образом, вы можете использовать такой код:
var tc = new Windows.Devices.Input.TouchCapabilities();
var touchPoints = 0;
if (tc.touchPresent) {
touchPoints = tc.contacts;
}
Примечание. В веб-контексте, где WinRT недоступна, некоторые данные о возможностях по вводу данных могут быть получены с помощью свойств элементов DOM ), ), и ). Это так же работает в локальном контексте.
Вы могли заметить, что возможности, перечисленные выше, ничего не сообщают о пере или ручке. Для них, а так же для более подробной информации обо всех устройствах для работы с указателями, включая сенсорный экран и мышь, у нас есть метод ), каждый из которых имеет следующие свойства:
touch, pen, или mouse.maxContacts – максимальное количество контактных точек, которое может поддерживать устройство. Обычно 1 для мыши и пера, и любое другое количество для сенсорного экрана.isIntegrated – значение true говорит о том, что устройство ввода встроено в компьютер, то есть на его присутствие можно рассчитывать. Значение false указывает на периферийное устройство, которое может отключить пользователь.physicalDeviceRect – этот объект типа Windows.Foundation.Rect предоставляет ограничивающий прямоугольник, в виде которого устройство воспринимает свою рабочую поверхность. Часто разрешение ввода сенсорного экрана не совпадает с экранными пикселями, что означает, что устройство ввода не способно выделить в точности один пиксель. Один из моих ноутбуков с сенсорным экраном, например, показывает это разрешение как 968x548 для экрана разрешением 1366x768 пикселей (как сообщает screenRect ниже). Рабочая поверхность мыши, с другой стороны, обычно один в один совпадает с экранным разрешением. Это может быть важно для приложений для рисования, которые работают с пером, если разрешение ввода меньше, чем разрешение экрана, это может означать некоторую неточность при переводе координат ввода данных в экранные пиксели.screenRect – этот объект типа Windows.Foundation.Rect предоставляет ограничивающий прямоугольник для экрана устройства, то есть, минимальные и максимальные координаты, на которые вам следует рассчитывать, обрабатывая события устройства. Этот прямоугольник принимает в расчет системы с несколькими мониторами, и он подстраивается под масштабирование разрешения.Пример "Ввод данных: возможности устройств" (http://code.msdn.microsoft.com/windowsapps/Input-device-capabilities-31b67745) в Windows SDK получает эту информацию и выводит ее на экран посредством кода в js/pointer.js. Я не привожу здесь этот код, так как все, что он делает – это обходит массив, создает длинную HTML-строку и помещает ее в DOM. В имитаторе выходные данные выглядят следующим образом. Обратите внимание на то, что имитатор, в данном случае, сообщает о наличии мыши и сенсорного экрана.
Любопытная фальсификация? Интересно то, что я запустил этот пример в отладчике Visual Studio на локальном компьютере, на ноутбуке, который совершенно определенно не имеет сенсорного экрана, но о наличии сенсорного устройства ввода, все равно, сообщалось, как на вышеприведенном изображении. Почему? Потому, что все еще был запущен имитатор Visual Studio, который добавляет виртуальное сенсорное устройство к аппаратному профилю. После того, как симулятор был полностью закрыт (а не только свернут в значок), я получил точные сведения о возможностях моего ноутбука. Так что помните об этом, если вы пишете программный код для проверки конкретных возможностей.
Пробовали удаленную отладку? Говоря об отладке, как упомянуто во врезке в лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", тестирование приложений на устройствах с разными возможностями – это отличная возможность для применения удаленной отладки в Visual Studio. Если вы еще не сделали этого, сделайте, все настойки займут лишь несколько минут. Для того, чтобы узнать подробности, обратитесь к материалу "Выполнение приложений для Магазина Windows на удаленном компьютере" (http://msdn.microsoft.com/library/windows/apps/hh441469%28v=vs.110%29.aspx).
В любой ситуации, когда вы хотите напрямую работать с сенсорным экраном, мышью или пером, возможно, для реализации части языка касаний подобным образом, используйте события MSPointer*. Большинство приложений для рисования или художественной обработки изображений, например, используют эти события для отслеживания и отображения на экране результатов взаимодействия с пользователем. Снова напомню, что указатель – это способ для рассмотрения ввода данных, имеющий более низкий уровень, чем жесты, что мы увидим в следующем разделе. Какие модели ввода данных вы испоьзуете, зависит от типа событий, с которыми вы хотите работать.
Совет. События указателей не вызываются, если система пытается выполнить манипуляцию наподобие сдвига или масштабирования. Для того чтобы отключить у элемента манипуляции, задайте -ms-content-zooming: none или -ms-touch-action: none, и избегайте использования стилей -ms-touch-action в pan-x, pan-y, pinch-zoom, и manipulation.
Как и в слудчае с другими событиями, вы можете прослушивать события MSPointer* для любых подходящих элементов, помня, опять же, что эти события транслируются в традиционные события мыши, поэтому не следует прослушивать и те и другие. Специальные события, которые описаны ниже, даны в порядке их типичной последовательности:
msReleasePointerCapture.) Обратите внимание на то, что если указатель был перемещен за пределы элемента и освобожден, элемент получит событие MSPointerOut, но не MSPointerUp.Это – те имена, которые используют с addEventListener. Эквивалентные имена свойств имеют, как обычно, форму onmspointerdown. Должно быть очевидным то, что некоторые из этих событий могут не вызываться указателями всех типов. Сенсорные экраны, например, обычно не вызывают события зависания указателя над элементом, хотя некоторые из них, те, что могут определять близость пальца, способны на это.
Совет. Если по каким-то причинам вы хотите предотвратить трансляцию события MSPointer* в традиционное событие мыши, вызовите метод eventArgs.preventDefault внутри соответствующего обработчика события.
Упражнение PointerEvents, которое можно найти среди дополнительной информации к курсу, как показано на рис. 3.1., позволяет вам увидеть, что происходит с событиями мыши, указателей, жестов, выборочно показывая группы событий на экране.
(рис 3.1) Экран упражнения PointerEvents (экран слегка обрезан для показа подробностей)
Внутри обработчиков для всех событий MSPointer*, объект eventArgs содержит полный набор свойств. Одно из них, pointerType, идентифицирует тип устройства ввода: серсорная панель (2), ручка (3), и мышь (4). Эти свойства позволяют вам, если нужно, реализовывать различное поведение для различных способов ввода. Каждый объект события так же содержит укникальное значение pointerId, которое содержит информацию о штрихе или линии для конкретной точки контакта, что позволяет согласовывать первоначальное событие MSPointerDown с последующими событиями. Когда мы взглянем, в следующем разделе, на жесты, мы так же увидим, как ипользовать pointerId события MSPointerDown для сопоставления жеста с указателем.
Полный набор свойств, который поступает вместе с событием, на самом деле, слишком велик, чтобы его здесь приводить, так как он содержит множество обычных свойств DOM (http://msdn.microsoft.com/library/windows/apps/hh831236.aspx) вместе со свойствами, имеющими отношение к указателю, из объекта типа ). Лучший способ посмотреть, что там находится – это запустить какой-нибудь код, наподобие примера "Ввод данных: обработка события указателя DOM" (http://code.msdn.microsoft.com/windowsapps/Input-DOM-pointer-and-2e5697ed) (это – приложение для рисования на элементе управления canvas), установить точку останова внутри обработчика одного из событий, и посмотреть на объект события. Нижеприведенная таблица описывает некоторые из свойсвт (и несколько методов), имеющих отношение к нашей беседе.
| Свойства | Описание |
|---|---|
currentPoint |
Объект типа ) . Он содержит множество других свойств, таких, как pointerDevice (объект Windows.Input.Device.PointerDevice как онисано ранее в этой лекции) и свойство, имеющее название properties, являющееся объектом типа Windows.UI.Input.PointerPointProperties. |
pointerType |
Источником события может быть сенсорная панель, перо или мышь: MSPOINTER_TYPE_TOUCH (2), MSPOINTER_TYPE_PEN (3), and MSPOINTER_TYPE_MOUSE (4). Вы можете использовать это, если необходимы различные действия в зависимости от типа устройства ввода. |
pointerId |
Уникальный идентификатор контакта. Он остается тем же самым в течение времени существования указателя. Если нужно, вы можете вызвать ) с этим идинтификатором для получения объекта PointerDevice (http://msdn.microsoft.com/library/windows/apps/windows.devices.input.pointerdevice.aspx), который описывает возможности устройства ввода, как описано выше в данной лекции. |
type |
Имя события, как, например, "MSPointerDown". |
x, screenX, y, screenY |
Координаты X и Y центральной точки указателя, спозиционированные относительно экрана. |
clientX, clientY |
Координаты X и Y центральной точки указателя, спозиционированные относительно пользовательской области приложения. |
offsetX, offsetY |
Координаты X и Y центральной точки указателя, спозиционированные относительно элемента. |
button |
Определяет кнопку, нажатую пользователем (на мыши или другом устройстве ввода с кнопками). Левой кнопке соответствует значение 0, средней – 1, правой – 2. Эти значения могут комбинироваться с помощью побитовой операции OR для одновременного нажатия нескольких кнопок (chord). |
ctrlKey, altKey, shiftKey |
Показывает, была ли нажата определенная клавиша клавиатуры, когда произошло событие указателя. |
hwTimestamp |
Отметка времени (в микросекундах), показывающая время, когда событие было получено от устройства. |
relatedTarget |
Предоставляет элемент, соответствующий текущему событию
Provides the element related to the current event, например, событие MSPointerOut. Предоставляет элемент, к которому было осуществлено перемещение точки касания. Может иметь значение null.
|
isPrimary |
Показывает, является ли данный указатель основным в сценарии с несколькими касания (как указатель мыши). |
| Свойства, присутствующие в зависимости от поддержки устройством (если поддержки нет, будут иметь значение 0) | |
width, height |
Ширина контактной точки и высота, заданная pointerId. |
pressure |
Нажим ручки, нормализованное к диапазону значений 0 – 255. |
rotation |
Движение курсора по часовой стрелке вокруг собственной основной оси в диапазоне 0 – 359. |
tiltX |
Наклон влево-вправо от нормального положения датчика (обычно – от перпендикуляра к поверхности), значение в диапазоне от -90 (влево), до 90 (вправо). |
tiltY |
Наклон вперед-назад от нормального положения датчика (обычно – от перпендикуляра к поверхности) в диапазоне от -10 (вперед, от пользователя), до 90 (назад, к пользователю). |
| Методы | |
currentPoint, getCurrentPoint |
Предоставляет объект типа ) для текущего указателя ввода, соответствующее целевому элементу (currentPoint) или заданному элементу (getCurrentPoint) |
intermediatePoints,getIntermediatPoints |
Предоставляет историю PointerPoint для текущего указателя по отношению к целевому элементу (intermediatePoint) или заданному элементу (getIntermediatePoints) |
Весьма поучительно запустить вышеупомянутый пример на устройстве, поддерживающем несколько одновременных касаний, так как раздельная обработка каждого pointerId позволяет вам рисовать несколькими пальцами одновременно.
Обычно, при событиях касания и поднятия указателя, устанавливают или снимают захват указателя элементом. Доступны следующие методы для поддержки этих действий каждым элементом DOM. Они применимы к каждому конкретному pointerId.
| Метод | Описание |
|---|---|
msSetPointerCapture |
Захватывает pointerId для элемента, таким образом, события указателя поступают к этому элементу и не вызываются для других элементов (даже если указатель мыши находится вне этого элемента, внутри другого). MSGotPointerCapture так же будет вызвано для элемента. |
msReleasePointerCapture |
Прекращает захват, вызывает событие MSLostPointerCapture . |
msGetPointerCapture |
Возвращает элемент, захвативший указатель, если таковой имеется (в противном случае возвращает null). |
Мы можем увидеть в примере "Ввод данных: обработка события указателя DOM", где устанавливается захват указателя в событии MSPointerDown и указатель освобождается в событии MSPointerUp:
this.MSPointerDown = function (evt) {
canvas.msSetPointerCapture(evt.pointerId);
// ...
};
this.MSPointerUp = function (evt) {
canvas.msReleasePointerCapture(evt.pointerId);
// ...
};
Первое, что стоит узнать о событиях MSGesture*, это то, что они не вызываются автоматически, как события click и MSPointer*, и недостаточно просто добавить прослушиватель и завершить тем дело (как для click!). Вместо этого вам нужно выполнить некоторые настройки, которые сообщат системе, как именно должны происходить жесты, и вам нужно исползовать MSPointerDown для того, чтобы связать настройки жеста с конкретным PointerId. Это усложняет схему работы, делая возможным работу приложения с несколькими различными жестами, независимую их обработку, что похоже на то, как работают с событиями указателей. Представьте, например, приложение-головоломку (в некоторой мере оно представлено в одном из примеров "Примеры жестов" ниже), которое позволяет нескольким пользователям сидеть вокруг сенсорного экрана размером со стол и каждому из них работать с отдельной частью головоломки. Используя жесты, каждый из игроков может управлять отдельной частью (или двумя!), перемещать ее, вращать, возможно масштабировать для того, чтобы увидеть ее покрупнее, и, конечно, пробовать поместить кусок головоломки в нужное место. Для приложений Магазина Windows, написанных на JavaScript, полезно то, что приращения манипуляции для сконфигурированных элементов – для переноса, вращения и масштабирования – даются в координатном пространстве родительского элемента, что означает, что довольно просто перенести манипуляции в CSS-трансформации и таким образом сделать манипуляции видимыми. Коротко говоря, это означает большую гибкость там, где она нужна вам. Если вам это не нужно, вы можете использовать жесты простейшим способом. Посмотрим, как все это работает.
Первый шаг к приему событий жестов заключается в создании объекта ) и в связывании его с элементом, для которого вы хотите принимать события. В упражнении PointerEvents этому элементу дано имя divElement, вам нужно сохранить этот элемент в свойстве жеста target и сохранить объект жеста в свойстве элемента gestureObject для использования его событием MSPointerDown:
var gestureObject = new MSGesture(); gestureObject.target = divElement; divElement.gestureObject = gestureObject;
Установив эти связи, вы затем можете добавить прослушиватель события, как обычно. Пример кпоказывает полный набор из шести событий жестов:
divElement.addEventListener("MSGestureTap", gestureTap);
divElement.addEventListener("MSGestureHold", gestureHold);
divElement.addEventListener("MSGestureStart", gestureStart);
divElement.addEventListener("MSGestureChange", gestureChange);
divElement.addEventListener("MSGestureEnd", gestureEnd);
divElement.addEventListener("MSInertiaStart", inertiaStart);
Однако сейчас работа еще не завершена. Если это все, что вы сделаете в своем коде, вы еще не получите этих событий, так как каждый жест нужно связать с указателем. Это делается в обработчике события MSPointerDown:
function pointerDown(e) {
//Связываем данный указатель с целевым жестом
e.target.gestureObject.addPointer(e.pointerId);
}
Для того чтобы получить возможность выполнять жесты вращения и изменения масштабирования с помощью колеса мыши (а это следует сделать), добавьте обработчик для события wheel, установите pointerId для этого события в 1 (фиксированное значение для колесика мыши) и отправьте то, что получилось в ваш обработчик MSPointerDown:
divElement.addEventListener("wheel", function (e) {
e.pointerId = 1; // Фиксированный pointerId для MouseWheel
pointerDown(e);
});
Теперь события жестов готовы к поступлению в данный элемент. (Помните, что события колесика мыши, сами по себе, транслируются, Ctrl+колесо мыши – это масштабирование, Shift+Ctrl+колесо мыши – вращение). Более того, если возникнет дополнительное событие MSPointerDown для того же самого элемента с различными значениями pointerId, метод addPointer включит этот новый указатель в жест. Это автоматически активирует жесты изменения масштаба и вращения, которые основаны на нескольких точках касания.
Если вы запустите упражнение PointerEvents (установив флаги Ignore Mouse Events (Игнорировать события мыши) и Ignore Pointer Events (Игнорировать события указателя)), и начнете касаться экрана, касаться, удерживая палец на экране, выполнять касание и короткое перетаскивание (с помощью сенсорного экрана или мыши), вы увидите выходные данные, похожие на те, что приведены на рис.3.2
(рис 3.2) Упражнение PointerEvents, выходные данные для событий жестов (скриншот слегка обрезан для выделения деталей)
Снова хочу отметить, что события жестов вызываются в ответ на последовательность событий указателя, предлагая высокоуровневую интерпретацию низкоуровневых событий указателя. В процессе интерпретации происходит дифференцирование событий касания/удержания от событий начала/изменения/окончания, выясняется, как и когда началось событие MSInertiaStart, и что предпринимает распознаватель жестов, когда объекту MSGesture передаются несколько точек.
Начиная с жеста одного указателя, первый аспект дифференцирования – это порог перемещения указателя (pointer movement threshold). Когда распознаватель жестов обнаруживает событие MSPointerDown, он начинает наблюдать за событиями MSPointerMove для того, чтобы видеть, остаются ли они внутри порогового расстояния, которое является эффективной границей для событий касания и удерживания. Это предназначено для того, чтобы игнорировать небольшое дрожание мыши или точки касания, как показано на рисунке ниже (я бы сказал, что здесь это несколько преувеличено!), когда происходит касание, небольшое перемещение, после чего указатель поднимается, генерируется событие MSGestureTap:
Horizontal threshold (Горизонтальный порог перемещения)
Vertical threschold (Вертикальный порог перемещения)
Many events (Множество событий)
Различить события MSGestureTap и MSGestureHold позволяет временной порог (time threshold):
MSGestureTap происходит, когда за событием MSPointerDown следует событие MSPointerUp в пределах временного порога.
MSGestureHold происходит, когда за событием MSPointerDown следует событие MSPointerUp с превышением временного порога. В подобном случае, один раз, при пересечении временного порога, вызывается событие MSGestureHold с eventArgs.detail установленным в 1 (MSGESTURE_FLAG_BEGIN). При условии, что указатель все еще находится в пределах порога перемещения, событие MSGestureHold вызывается еще раз, когда происходит MSPointerUp, с eventArgs.detail установленным в 2 (MSGESTURE_FLAG_END). Вы можете увидеть эти детали в двух первых событиях на рис. 3.2. выше.
Флаги жестов в значении eventArgs.detail сопровождаются множеством других свойств, касающихся расположения и перемещения в объекте eventArgs, как показано в следующей таблице:
| Свойства | Описание |
|---|---|
screenX, screenY |
Координаты X и Y центральной точки жеста, спозиционированные |
clientX, clientY |
Координаты X и Y центральной точки жеста, спозиционированные относительно пользовательской области приожения. |
offsetX, offsetY |
Координаты X и Y центральной точки жеста, спозиционированные |
translationX,
translationY
|
Перенос по осям X и Y. |
velocityX,
velocityY
|
Скорость перемещения по осям X и Y. |
scale |
Коэффициент масштабирования (процентное изменение масштаба). |
expansion |
Скорость расширения области манипуляции. |
rotation |
Угол поворота в радианах. |
velocityAngular |
Угловая скорость в радианах. |
detail |
Содержит флаги жеста, которые описывают состояние события жеста. Эти флаги определены как значения в eventArgs:
eventArgs.MSGESTURE_FLAG_NONE (0): Указывает на текущий жест, такой, как MSGestureChange где представлены изменения координат.
eventArgs.MSGESTURE_FLAG_BEGIN (1): Начало последовательности жестов. Если взаимодействие включает в себя единственное событие, такое, как MSGestureTap, и флаг MSGESTURE_FLAG_BEGIN, и флаг MSGESTURE_FLAG_END будут установлены (значение 3).eventArgs.MSGESTURE_FLAG_END (2): Конец последовательности жестов. Опять же, если взаимодействие включает в себя единственный жест, такой, как MSGestureTap, и флаг MSGESTURE_FLAG_BEGIN, и флаг MSGESTURE_FLAG_END будут установлены (значение 3).eventArgs.MSGESTURE_FLAG_CANCEL (4): Жест был отменен. |
hwTimestamp |
Отметка времени, когда указатель был назначен системой при поступлении входных данных от устройства. |
Многие из этих свойств становятся гораздо интереснее, когда указатель выходит за пределы порога перемещения, после чего уже не произойдет события касания (tap) или удерживания (hold). Вместо этого, как только указатель пересечет порог, будет выполнено событие MSGestureStart, после чего возможен вызов событий MSGestureChange, их может не быть вовсе, но обычно их довольно много. В конце вызывается одно событие MSGestureEnd:
Обратите внимание на то, что если указатель не пересечет порог перемещения достаточно долго для вызова первого MSGestureHold с флагом MSGESTURE_FLAG_BEGIN, но затем указатель переместится за пределы порога, MSGestureHold будет вызван второй раз, с флагами MSGESTURE_FLAG_CANCEL | MSGESTURE_FLAG_END в eventArgs.detail (значение 6), за ним последует MSGestureStart с флагом MSGESTURE_FLAG_BEGIN. Подобная последовательность позволяет дифференцировать событие удержания (hold) от жестов прокрутки или перетаскивания, даже если пользователь какое-то время удерживал элемент на месте.
События MSGestureStart, MSGestureChange, и MSGestureEnd все вместе задают манипуляцию (manipulation) для элемента, с которым связан жест, когда указатель контактирует с элементом в течение манипуляции. Технически это означает, что указатель больше не перемещается, когда он освобождается.
Если указатель продолжает перемещаться после того, как он освобожден, тогда мы переключаемся с манипуляции на движение по инерции (inertial motion). В этом случае вызывается событие MSInertiaStart, оно показывает, что указатель продолжает несмотря на то, что контакт с элементом потерян, или указатель поднят. В результате, вы продолжаете получать события MSGestureChange до тех пор, пока движение не будет завершено:
С концептуальной точки зрения разница между манипуляцией и движением по инерции проиллюстрирована на рис. 3.3. Кривые, показанные здесь, не обязательно отражают реальные изменения между сообщениями. Если указатель переместился вдоль зеленой линии и болше не двигается после отпускания указателя, мы видим последовательность жестов, которая описывает манипуляцию. Если указатель отпущен при движении, мы видем событие MSInertiaStart между сериями событий MSGestureChange, и последовательность событий продолжается в виде оранжевой линии.
(рис 3.3) Концептуальное представление манипуляции (зеленая линия) и движения по инерции (оранжевая линия).
Возвращаясь к рис. 3.2., где выпадающий список Show (Показ) был установлен в значение Velocity (Скорость), выходные данные для событий MSGestureChange включали значения eventArgs.velocity*. В течение манипуляции, скорость может меняться с любой частотой, в зависимости от того, как движется указатель. Однако когда начинается движение по инерции, скорость постепенно падает до нуля, и тогда происходит событие MSGestureEnded. Количество событий изменения зависит от того, сколько времени нужно для того, чтобы продолжать замедляющееся, вплоть до остановки, движение, но если вы просто перемещаете элемент по экрану с помощью этих событий, несущих информацию об изменениях, пользователь увидит приятную плавную анимацию. Вы можете поэкспериментировать с этим в упражнении PointerEvents, используя выпадающий список Show для того, чтобы посмотреть, как на другие свойства позиционирования влияют различные жесты при манипуляциях и движении по инерции.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.