快速入门:捕获墨迹数据 (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 应用商店应用。

若要完成此教程,你需要:

说明

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 是用于启动墨迹捕获的事件。

    在此示例中,使用 beginPathmoveTo 方法在屏幕坐标中设置开始显示墨迹数据的位置。(捕获墨迹和显示墨迹是两个独立的操作。)然后,通过将事件的指针数据 (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,以确保此事件与相关联的 pointerdownpointermove 事件的 pointerId 相同。如果不相同,输入将被忽略,不捕获墨迹数据。

    调用 lineTostrokeclosePath 方法以完成和关闭在 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 应用商店应用示例主页上的以下墨迹示例:

相关主题

概念

响应笔和触笔输入

参考

Windows.Devices.Input

Windows.UI.Core

Windows.UI.Input

Windows.UI.Input.Inking

示例 (DOM)

输入:DOM 指针和手势处理示例

示例(Windows 应用商店应用  API)

输入:设备功能示例

输入:墨迹示例

输入:简化的墨迹示例