다음을 통해 공유


빠른 시작: 잉크 데이터 캡처(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 파일 1개("InkPage.html"), CSS 파일 1개("InkPage.css") 및 JavaScript 파일 1개("InkPage.js")를 포함했습니다.

전체 CSS, HTML 및 JavaScript 파일은 잉크 데이터 캡처 전체 코드에서 사용할 수 있습니다.

2. UI에서 그리기 화면 설정

이 예제에서는 Canvas 요소를 잉크 그리기 및 렌더링 화면으로 사용합니다.

canvas는 JavaScript로 작성한 Windows 스토어 앱에서 그래픽 요소를 동적으로 그리고 렌더링 및 조작하기 위한 화면으로 작동하는 HTML5 요소입니다.

참고  SVG(Scalable Vector Graphics) 개체도 사용할 수 있습니다.

 

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 요소의 그리기 컨텍스트(이 경우 2D 화면)가 할당됩니다.

// Obtain reference to the specified element.
function get(elementId)
{
    return document.getElementById(elementId);
}
inkCanvas = get("inkCanvas");
inkContext = inkCanvas.getContext("2d");

5. 이벤트 처리기 함수 정의

이 섹션에서는 포인터 입력에 필요한 다양한 이벤트 처리기를 정의합니다. 이러한 이벤트 처리기는 다음 단계에서 추가하는 이벤트 수신기와 연결됩니다.

  • pointerdown은 잉크 캡처를 시작하는 데 사용되는 이벤트입니다.

    다음 예제에서 beginPathmoveTo 메서드는 잉크 데이터 표시를 시작할 위치를 화면 좌표에 설정하는 데 사용됩니다. 잉크 캡처 및 표시는 별도의 두 동작입니다. pointerdown 이벤트는 이벤트의 포인터 데이터(currentPoint)를 ProcessPointerDown으로 전달하여 inkManager를 통해 처리됩니다.

    전역 변수 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는 이 이벤트의 pointerId가 관련된 pointerdown 이벤트의 해당 항목과 일치하도록 하는 데 사용됩니다. 그렇지 않은 경우 입력은 무시되고 잉크 데이터는 캡처되지 않습니다. 이러한 기능은 펜 스트로크 중에 우연히 마우스가 움직이면서 발생한 입력 등을 필터링하는 데 유용합니다.

    개별 직선 세그먼트처럼 바로 잉크 데이터를 그리고 표시하기 위해 lineTo(디지타이저에서 보고된 포인터의 RawPosition 사용) 및 stroke 메서드가 호출됩니다. 잉크 캡처 및 표시는 별도의 두 동작입니다. pointermove 이벤트는 이벤트의 포인터 데이터(currentPoint)를 ProcessPointerUpdate으로 전달하여 inkManager를 통해 처리됩니다.

        // 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가 관련된 pointerdownpointermove 이벤트의 해당 항목과 일치하도록 합니다. 그렇지 않은 경우 입력은 무시되고 잉크 데이터는 캡처되지 않습니다.

    lineTo, strokeclosePath 메서드는 handlePointerDown 함수에서 만든 경로를 완료하고 닫기 위해 호출합니다. pointerup 이벤트는 이벤트의 포인터 데이터(currentPoint)를 ProcessPointerUp으로 전달하여 inkManager를 통해 처리됩니다.

    이 예제에서 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)

입력: 장치 접근 권한 값 샘플

입력: 잉크 샘플

입력: 간단한 잉크 샘플