クイック スタート: インク データのキャプチャ (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 ストア アプリで、インク プラットフォームを使って、ポインター デバイス (マウス、ペン/スタイラス、またはタッチ) からの入力を検出してキャプチャする方法を理解できます。

必要条件

JavaScript 用 Windows ライブラリのテンプレートが使われた JavaScript を使った基本的な Windows ストア アプリの作成経験が必要です。

このチュートリアルを行うには、次の作業を行う必要があります。

手順

1. Visual Studio で新しい "[空のアプリケーション]" プロジェクトを作って、HTML、CSS、JavaScript ファイルを追加する

この例では、HTML ファイル ("InkPage.html")、CSS ファイル ("InkPage.css")、JavaScript ファイル ("InkPage.js") を 1 つずつ使います。

完全な CSS、HTML、JavaScript ファイルについては、「インク データのキャプチャのコード一式」をご覧ください。

2. UI に描画面を設定する

この例では、インクの描画とレンダリングのサーフェスとして Canvas 要素を使います。

canvas は、JavaScript を使った Windows ストア アプリでグラフィック要素を動的に描画、レンダリング、操作するためのサーフェスとして機能する HTML5 要素です。

  スケーラブル ベクター グラフィックス (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 とその子要素を操作するには、2 つの変数を定義する必要があります。

最初の変数 (inkCanvas) には、getElementById を使って、canvas 要素への参照 "inkCanvas" が割り当てられます。2 番目の変数 (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 メソッドを使って、インク データの表示を開始する画面上の座標を設定しています (インクのキャプチャとインクの表示は 2 つの個別のアクションです)。その後、pointerdown イベントは、inkManager からイベントのポインター データ (currentPoint) が ProcessPointerDown に渡されることによって処理されます。

    グローバル変数 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 が同じになるようにしています。これが同じでない場合、入力は無視され、インク データはキャプチャされません。これはペン ストローク中に誤って移動したマウスからの入力をフィルター処理する場合などに便利です。

    (デジタイザーから報告されたポインターの RawPosition を使う) lineTo メソッドと、stroke メソッドを呼び出して、個別の直線セグメントとして即座にインク データを描画し、表示します (インクのキャプチャとインクの表示は 2 つの個別のアクションです)。その後、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 を使って、このイベントとこれに関連付けられている pointerdown イベントおよび pointermove イベントの pointerId が同じになるようにしています。これが同じでない場合、入力は無視され、インク データはキャプチャされません。

    lineTostrokeclosePath の各メソッドを呼び出して、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 ストア アプリ サンプルのホーム ページにある次のインクのサンプルをビルドして実行します。

関連トピック

概念

ペン入力とスタイラス入力への反応

リファレンス

Windows.Devices.Input

Windows.UI.Core

Windows.UI.Input

Windows.UI.Input.Inking

サンプル (DOM)

入力: DOM ポインター イベント処理のサンプルに関するページ

サンプル (Windows ストア アプリ API)

入力: デバイス機能のサンプルに関するページ

入力: インクのサンプルに関するページ

入力: 簡略化されたインクのサンプルに関するページ