快速入门:捕获墨迹数据 (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 引入了多个更新和改善措施。请参阅 Windows 8.1 的 API 更改获取详细信息。
目标: 完成本快速入门之后,你将了解如何在使用 JavaScript 的 Windows 应用商店应用中使用墨迹平台检测和捕获指针设备(鼠标、笔/触笔或触摸屏)的输入。
先决条件
我们假设你可以创建使用 Windows JavaScript 库模板的使用 JavaScript 的基本 Windows 应用商店应用。
若要完成此教程,你需要:
- 安装 Windows 8
- 安装 Microsoft Visual Studio。
- 获取开发人员许可证。有关说明,请参阅使用 Visual Studio 2013 开发。
- 创建第一个采用 JavaScript 的 Windows 应用商店应用。
- 查看快速入门:添加 WinJS 控件和样式了解有关 WinJS 对象和控件的信息。
说明
1. 在 Visual Studio 中创建一个新的"空白应用"并添加 HTML、CSS 和 JavaScript 文件
在本示例中,我们拥有一个 HTML 文件 ("InkPage.html"),一个 CSS 文件 ("InkPage.css") 以及一个 JavaScript 文件 ("InkPage.js")。
可以在捕获墨迹数据完整代码中找到完整的 CSS、HTML 和 JavaScript 文件。
2. 在你的 UI 中设置绘图图面
此示例使用 Canvas 元素作为墨迹绘图和呈现图面。
canvas 是一种 HTML5 元素,该元素在使用 JavaScript 的 Windows 应用商店应用中充当动态绘图、渲染以及处理图形元素的图面。
注意 也可以使用可缩放的矢量图形 (SVG) 对象。
在 HTML 文件中,声明 canvas 元素并为其提供 "inkCanvas" 的 id
。使用此 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
) 通过使用 getElementById 分配对 canvas 元素 "inkCanvas" 的引用。第二个变量 (inkContext
) 使用 getContext 方法分配 canvas元素(在此情况下,为 2-D 图面)的绘图上下文。
// Obtain reference to the specified element.
function get(elementId)
{
return document.getElementById(elementId);
}
inkCanvas = get("inkCanvas");
inkContext = inkCanvas.getContext("2d");
5. 定义事件处理程序函数
在本节中,我们定义指针输入所需的各种事件处理程序。这些处理程序将与你在下一步中添加的时间侦听器相关联。
pointerdown 是用于启动墨迹捕获的事件。
在此示例中,使用 beginPath 和 moveTo 方法在屏幕坐标中设置开始显示墨迹数据的位置。(捕获墨迹和显示墨迹是两个独立的操作。)然后,通过将事件的指针数据 (currentPoint) 传递到 ProcessPointerDown,来使用
inkManager
处理 pointerdown 事件。使用全局变量
penID
存储与该事件关联的输入指针的 pointerId。我们将在后面讨论此需求。注意 此示例筛选指针输入(使用 pointerType 属性),以便只在按下鼠标左键时为笔/触笔输入以及鼠标输入执行墨迹捕获。触控输入被保留用于操作该应用的 UI。
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
用于确保此事件与相关联的 pointerdown 事件的 pointerId 相同。如果不相同,输入将被忽略,不捕获墨迹数据。这可用于过滤掉在笔划输入过程中意外移动鼠标造成的输入。调用 lineTo(使用数字化器所报告的指针的 RawPosition)和 stroke 方法来以离散线段方式绘制和即时显示墨迹数据。(捕获墨迹和显示墨迹是两个独立的操作。)然后,通过将事件的指针数据 (currentPoint) 传递到 ProcessPointerUpdate,来使用
inkManager
处理 pointermove 事件。// 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
,以确保此事件与相关联的 pointerdown 和 pointermove 事件的 pointerId 相同。如果不相同,输入将被忽略,不捕获墨迹数据。调用 lineTo、stroke 和 closePath 方法以完成和关闭在
handlePointerDown
函数中创建的路径。然后,通过将事件的指针数据 (currentPoint) 传递到 ProcessPointerUp,来使用inkManager
处理 pointerup 事件。此示例中的
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。
- 当与 pointerdown 事件关联的指针在 canvas 上移动时引发 pointermove。
- 当用户从数字化器表面抬起笔或手指或者释放鼠标左键时引发 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 应用商店应用示例主页上的以下墨迹示例:
- 输入:简化的墨迹示例 - 此示例演示墨迹功能,如保存和加载墨迹、选择墨迹和删除墨迹、通过手写识别将笔划墨迹转换为文本。
- 输入:墨迹示例 - 除了输入:简化的墨迹示例中演示的功能之外,该示例还提供一个更加丰富的 UI 并且演示如何在识别结果中进行搜索。
相关主题
概念
参考
示例 (DOM)
示例(Windows 应用商店应用 API)