Краткое руководство. Захват рукописного ввода (HTML)
[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. При разработке приложений для Windows 10 см. раздел последняя документация]
В этом кратком руководстве содержатся инструкции по захвату данных рукописного ввода, получаемых от дигитайзера ввода.
Примечание В этом разделе используется код из полностью функционального проекта Microsoft Visual Studio 2013 на JavaScript. Хотя проект недоступен для скачивания, полностью файлы каскадных таблиц стилей (CSS), HTML и JavaScript можно найти в разделе Полный код захвата рукописного ввода.
Обновления в Windows 8.1: В Windows 8.1 появилось множество обновлений и усовершенствований API ввода с помощью указателя. Дополнительные сведения см. в разделе Изменения API для Windows 8.1.
Цель: Изучив это краткое руководство, вы поймете, как использовать платформу рукописного ввода для обнаружения и захвата ввода с указывающего устройства (мышь, перо, сенсорный экран) в приложении Магазина Windows на JavaScript.
Необходимые условия
Предполагается, что вы умеете создавать простые приложения Магазина Windows на JavaScript с помощью шаблона библиотеки Windows для JavaScript.
Для выполнения этого руководства вам необходимо:
- Установить Windows 8
- Установить Microsoft Visual Studio.
- Получить лицензию разработчика. Инструкции см. в разделе о разработке с помощью Visual Studio 2013.
- Создание первого приложения Магазина Windows на JavaScript.
- Сведения об объектах и элементах управления WinJS см. в документе Краткое руководство: добавление элементов управления и стилей WinJS.
Инструкции
1. Создайте новый проект "Пустое приложение" в Visual Studio и добавьте файлы HTML, CSS и JavaScript.
В данном примере используются один HTML-файл ("InkPage.html"), один CSS-файл ("InkPage.css") и один файл JavaScript ("InkPage.js").
Полностью файлы CSS, HTML и JavaScript можно найти в разделе Полный код захвата рукописного ввода.
2. Настройте поверхность конструктора в вашем пользовательском интерфейсе
Данный пример использует элемент Canvas для отрисовки и обработки рукописного ввода.
canvas — это элемент HTML5, выполняющий роль поверхности для графических элементов, которые динамически отрисовываются, обрабатываются и изменяются в приложении Магазина Windows на JavaScript.
Примечание Также можно использовать объект масштабируемой векторной графики.
В HTML-файле объявите элемент canvas и присвойте ему идентификатор (id
) "inkCanvas". Используйте этот идентификатор (id
) для ссылки на элемент из файла JavaScript.
<body>
<div id="applicationTitle">Ink sample</div>
<div>
<canvas id="inkCanvas"></canvas>
<div>
<button id="load">Load</button>
<button id="save">Save</button>
<button id="draw">Draw</button>
<button id="select">Select</button>
<button id="selectall">Select all</button>
<button id="erase">Erase</button>
<button id="eraseAll">Erase all</button>
<button id="recognize" value="selected">Handwriting recognition</button>
</div>
</div>
<div id="modeMessage"></div>
<div id="deviceMessage"></div>
<div id="statusMessage"></div>
</body>
3. Создайте диспетчер рукописного ввода
Объект InkManager обрабатывает и изменяет данные рукописного ввода, полученные через ввод указателем.
В файле JavaScript создайте диспетчер рукописного ввода. В данном примере объект InkManager является глобальным.
// Create an ink manager.
// InkManager is documented at https://go.microsoft.com/fwlink/?LinkID=260648.
var inkManager = new Windows.UI.Input.Inking.InkManager();
4. Подключите ваше приложение к поверхности конструктора
Для работы с объектом canvas и его дочерними элементами необходимо определить две переменные.
Первой переменной (inkCanvas
) присваивается ссылка на элемент canvas, "inkCanvas", при помощи метода getElementById. Второй переменной (inkContext
) присваивается контекст прорисовки элемента canvas (двухмерная поверхность в данном случае) при помощи метода getContext.
// Obtain reference to the specified element.
function get(elementId)
{
return document.getElementById(elementId);
}
inkCanvas = get("inkCanvas");
inkContext = inkCanvas.getContext("2d");
5. Определите функции обработчика событий
В этом разделе мы определим различные обработчики событий для ввода указателем. Они будут связаны с прослушивателями событий, которые вы добавите на следующем шаге.
pointerdown — событие, которое используется для начала записи рукописного ввода.
В этом примере методы beginPath и moveTo используются для задания экранных координат места, где необходимо начать отображение данных рукописного ввода. (Запись и отображение рукописного ввода — это два отдельных действия.) Затем событие pointerdown обрабатывается с помощью
inkManager
, передавая данные указателя (currentPoint) события на ProcessPointerDown.Глобальная переменная
penID
используется для хранения pointerId указателя ввода, связанного с этим событием. О необходимости использования такой переменной мы расскажем позже.Примечание Этот пример фильтрует ввод указателя (с помощью свойства pointerType) так, что сбор рукописного ввода осуществляется только для ввода пера и мыши, если нажата левая кнопка мыши. Сенсорный ввод зарезервирован для изменения пользовательского интерфейса вашего приложения.
function getPointerDeviceType(pId) { var pointerDeviceType; var pointerPoint = Windows.UI.Input.PointerPoint.getCurrentPoint(pId); switch (pointerPoint.pointerDevice.pointerDeviceType) { case Windows.Devices.Input.PointerDeviceType.touch: pointerDeviceType = "Touch"; break; case Windows.Devices.Input.PointerDeviceType.pen: pointerDeviceType = "Pen"; break; case Windows.Devices.Input.PointerDeviceType.mouse: pointerDeviceType = "Mouse"; break; default: pointerDeviceType = "Undefined"; } deviceMessage.innerText = pointerDeviceType; return pointerDeviceType; }
// Occurs when the pointer (touch, pen, mouse) is detected by the canvas. // Each stroke begins with onPointerDown. function onPointerDown(evt) { // Get the device type for the pointer input. pointerDeviceType = getPointerDeviceType(evt.pointerId); // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === 0))) { statusMessage.innerText = pointerDeviceType + " pointer down: Start stroke. " // Process one pointer at a time. if (pointerId === -1) { var current = evt.currentPoint; // Start drawing the stroke. inkContext.beginPath(); inkContext.lineWidth = strokeWidth; inkContext.strokeStyle = strokeColor; inkContext.moveTo(current.position.x, current.position.y); // Add current pointer to the ink manager (begin stroke). inkManager.processPointerDown(current); // The pointer id is used to restrict input processing to the current stroke. pointerId = evt.pointerId; } } else { // Process touch input. } }
Данные рукописного ввода записываются при возникновении события pointermove.
В следующем примере глобальная переменная
penId
позволяет убедиться, что свойство pointerId для этого события идентично свойству, связанному с событием pointerdown. Если это не так, ввод игнорируется и рукописный ввод не записывается. Такая проверка полезна, например, для отфильтровывания ввода с помощью мыши, которая случайно переместилась во время движения пера.Метод lineTo (с использованием параметра RawPosition указателя согласно сообщению дигитайзера) и методы stroke вызываются для немедленной прорисовки и отображения данных рукописного ввода в виде отдельных сегментов линии. (Запись и отображение рукописного ввода — это два отдельных действия.) Затем событие pointermove обрабатывается с помощью
inkManager
, передавая данные указателя (currentPoint) события на ProcessPointerUpdate.// Mouse: Occurs when the pointer moves. // Pen/Touch: Occurs at a steady rate (approx. 100 messages/second) whether the pointer moves or not. function onPointerMove(evt) { // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === -1))) { statusMessage.innerText = pointerDeviceType + " pointer move: Draw stroke as lines. " // The pointer Id is used to restrict input processing to the current stroke. // pointerId is updated in onPointerDown(). if (evt.pointerId === pointerId) { var current = evt.currentPoint; // Draw stroke in real time. inkContext.lineTo(current.rawPosition.x, current.rawPosition.y); inkContext.stroke(); // Add current pointer to the ink manager (update stroke). inkManager.processPointerUpdate(current); } } else { // Process touch input. } }
Запись данных рукописного ввода завершается при возникновении события pointerup.
Как и в предыдущем примере, эта функция использует глобальную переменную
penId
, чтобы проверить, идентично ли свойство pointerId для этого события свойству, связанному с событиями pointerdown и pointermove. Если это не так, ввод игнорируется и рукописные данные не записываются.Методы lineTo, stroke и closePath вызываются, чтобы завершить и закрыть контур, созданный в функции
handlePointerDown
. Затем событие pointerup обрабатывается с помощьюinkManager
, передавая данные указателя (currentPoint) события на ProcessPointerUp.В этом примере вызывается дополнительная функция
renderAllStrokes
для обработки данных рукописного ввода и преобразования необработанных сегментов росчерка в элемент canvas в виде плавных кривых (см. раздел Обработка данных рукописного ввода).// Occurs when the pointer (touch, pen, mouse) is lifted from the canvas. // Each stroke ends with onPointerUp. function onPointerUp(evt) { // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === 0))) { statusMessage.innerText = pointerDeviceType + " pointer up: Finish stroke. " if (evt.pointerId === pointerId) { // Add current pointer to the ink manager (end stroke). inkManager.processPointerUp(evt.currentPoint); // End live drawing. inkContext.closePath(); // Render strokes using bezier curves. renderAllStrokes(); // Reset pointer Id. pointerId = -1; } } else { // Process touch input. } }
См. ссылки на более сложные примеры в разделе "Связанные темы" в нижней части страницы.
6. Подключите прослушиватели событий ввода к поверхности конструктора
Используя ссылку на элемент canvas, подключите прослушиватели PointerEvent и свяжите их с обработчиками событий указателя, определенными на предыдущем шаге.
- Событие pointerdown возникает, когда пользователь нажимает пером или пальцем на поверхность дигитайзера либо щелкает левой кнопкой мыши.
- Событие pointermove возникает, когда указатель, связанный с событием pointerdown, перемещается по canvas.
- Событие pointerup возникает, когда пользователь убирает перо или палец с поверхности дигитайзера или отпускает левую кнопку мыши.
// Set up the handlers for input processing.
inkCanvas.addEventListener("pointerdown", onPointerDown, false);
inkCanvas.addEventListener("pointermove", onPointerMove, false);
inkCanvas.addEventListener("pointerup", onPointerUp, false);
Сводка
Теперь вы имеете представление о том, как захватывать данные рукописного ввода с помощью своего приложения Магазина Windows.
Чтобы понаблюдать за действием этого кода, выполните сборку и запустите образцы рукописного ввода, представленные на домашней странице образцов приложений Магазина Windows:
- Ввод: упрощенный образец рукописного ввода — показывает дополнительные функциональные возможности, такие как сохранение и загрузка или выбор и удаление рукописного фрагмента, а также преобразование росчерков пера в текст с помощью функции распознавания рукописного ввода.
- Ввод: образец рукописного ввода — помимо функциональности, продемонстрированной в разделе Ввод: образец рукописного ввода, предоставляет пользовательский интерфейс с более широкими возможностями и демонстрирует поиск в результатах распознавания.
Связанные разделы
Понятия
Реакция на ввод с помощью пера
Справочные материалы
Примеры (DOM)
Ввод: пример обработки событий указателя DOM
Примеры (API приложения Магазина Windows)
Ввод: пример возможностей устройства