터치 이벤트 - 레벨 2

최종 커뮤니티 그룹 보고서

이 버전:
https://www.w3.org/community/reports/touchevents/CG-FINAL-touch-events-20240704/
최신 게시 버전:
https://www.w3.org/community/reports/touchevents/CG-FINAL-touch-events-20240704/
최신 편집자 초안:
https://w3c.github.io/touch-events/
편집자:
Doug Schepers (W3C)
Sangwhan Moon (Opera Software ASA)
Matt Brubeck (Mozilla)
Arthur Barstow (초청 전문가)
Rick Byers (Google)
Patrick H. Lauke (TetraLogical)
저장소
GitHub에 있습니다.
버그 신고
커밋 기록
메일링 리스트

이 문서의 상태

이 명세서는 Touch Events Community Group에서 발표했습니다. 이것은 W3C 표준이 아니며 W3C 표준 절차에 있는 문서도 아닙니다. 다음을 유의하세요: W3C Community Final Specification Agreement (FSA)에 따라 다른 조건이 적용됩니다. 자세한 내용은 W3C 커뮤니티 및 비즈니스 그룹을 참조하세요.

이 명세서는 Touch Events Community Group에서 발표했습니다. 이것은 W3C 표준이 아니며 W3C 표준 절차에 있는 문서도 아닙니다.

다음을 유의하세요: W3C Community Final Specification Agreement (FSA)에 따라 다른 조건이 적용됩니다.

이 명세서의 이 버전은 Touch Events Level 1에 대한 수정 및 개선을 포함하며, 이전에 발표된 Touch Event Extensions의 기능을 통합합니다.

참고

현재 Touch Events에 대해 추가 작업을 계속할 의도는 없습니다. 이 문서는 원래 Touch Events Level 1 명세의 발표 이후 사용자 에이전트에서 이루어진 추가 및 변경 사항을 반영하도록 유지되었습니다. 커뮤니티 그룹은 Touch Events를 레거시 API로 간주하므로, 작성자는 대신 Pointer Events를 채택할 것을 강력히 권장합니다.

초록

Touch Events 명세는 터치 민감 표면과의 하나 이상의 접점과, 그 접점들이 표면 및 표면 위에 표시되는 모든 DOM 요소(예: 터치 스크린) 또는 표면과 연관된 요소(예: 디스플레이가 없는 드로잉 태블릿)에 대해 어떻게 변하는지를 나타내는 일련의 저수준 이벤트를 정의합니다. 또한 스타일러스의 기능을 고려하여 드로잉 태블릿과 같은 펜-태블릿 장치도 다룹니다.

1. 서론

이 절은 비규범적입니다.

웹 애플리케이션에 터치 입력을 제공하는 터미널에서 실행되는 사용자 에이전트는 일반적으로 해석된 마우스 이벤트를 사용하여 사용자가 대화형 웹 애플리케이션에 접근할 수 있도록 합니다. 그러나 이러한 해석된 이벤트는 물리적 터치 입력을 기반으로 정규화된 데이터이기 때문에 의도한 사용자 경험을 전달하는 데 한계가 있습니다. 또한 마우스 이벤트의 제약(시스템 수준의 제한 및 레거시 호환성)으로 인해 장치의 기능과 관계없이 동시 입력을 처리할 수 없습니다.

한편, 네이티브 애플리케이션은 제공되는 시스템 API를 통해 두 경우 모두를 처리할 수 있습니다.

Touch Events 명세는 웹 애플리케이션이 터치 이벤트와, 기능을 갖춘 장치의 다중 터치 포인트를 직접 처리할 수 있도록 인터페이스를 지정함으로써 이 문제에 대한 해결책을 제공합니다.

2. 적합성

비규범적으로 표시된 절 외에도, 이 명세서의 모든 작성 지침, 다이어그램, 예제 및 참고는 비규범적입니다. 이 명세서의 나머지 모든 내용은 규범적입니다.

이 문서에서 핵심 단어 MUST는 여기와 같이 모두 대문자로 표시될 때에 한해 BCP 14 [RFC2119] [RFC8174] 에 설명된 대로 해석됩니다.

이 명세서는 포함된 인터페이스를 구현하는 단일 제품, 즉 해당 인터페이스를 구현하는 사용자 에이전트에 적용되는 적합성 기준을 정의합니다.

WindowProxy는 [HTML5]에 정의되어 있습니다.

2.1 WebIDL 적합성

이 명세서의 IDL 블록은 WebIDL 명세에서 정의한 적합한 IDL 단편입니다 [WEBIDL].

적합한 사용자 에이전트는 또한 이 명세의 IDL 단편에 대한 적합한 JavaScript 구현체여야 하며, 다음 예외가 있습니다:

참고: IDL 속성을 반영하는 두 방식 모두 플랫폼 객체에서 단순히 해당 속성을 읽고 쓰는 것이 동작하도록 허용합니다. 예를 들어, Touch 객체 aTouch가 주어졌을 때, aTouch.target을 평가하면 Touch 객체의 EventTarget이 반환됩니다. 사용자 에이전트가 IDL 속성을 접근자 속성으로 구현한 경우, 속성 접근은 getter를 호출하여 EventTarget을 반환합니다. 사용자 에이전트가 접근자 속성과 동일한 동작을 갖는 데이터 속성으로 플랫폼 객체에 구현한 경우, 객체는 자신의 속성으로 target을 가지며 그 값은 EventTarget 객체가 되고, 속성 접근은 이 값을 반환합니다.

3. Touch 인터페이스

이 인터페이스는 터치 이벤트의 개별 터치 포인트를 설명합니다. Touch 객체는 불변이며; 생성된 이후에는 그 속성이 변경되어서는 안 됩니다.

WebIDLenum TouchType {
    "direct",
    "stylus"
};

dictionary TouchInit {
    required long        identifier;
    required EventTarget target;
             double      clientX = 0;
             double      clientY = 0;
             double      screenX = 0;
             double      screenY = 0;
             double      pageX = 0;
             double      pageY = 0;
             float       radiusX = 0;
             float       radiusY = 0;
             float       rotationAngle = 0;
             float       force = 0;
             double      altitudeAngle = 0;
             double      azimuthAngle = 0;
             TouchType   touchType = "direct";
};

[Exposed=Window]
interface Touch {
    constructor(TouchInit touchInitDict);
    readonly        attribute long        identifier;
    readonly        attribute EventTarget target;
    readonly        attribute double      screenX;
    readonly        attribute double      screenY;
    readonly        attribute double      clientX;
    readonly        attribute double      clientY;
    readonly        attribute double      pageX;
    readonly        attribute double      pageY;
    readonly        attribute float       radiusX;
    readonly        attribute float       radiusY;
    readonly        attribute float       rotationAngle;
    readonly        attribute float       force;
    readonly        attribute float       altitudeAngle;
    readonly        attribute float       azimuthAngle;
    readonly        attribute TouchType   touchType;
};
identifier

터치 포인트에 대한 식별 번호입니다.

터치 포인트가 활성화되면, 활성 상태인 다른 모든 터치 포인트와 구별되는 identifier가 할당되어야 합니다. 터치 포인트가 활성 상태인 동안, 해당 터치 포인트를 참조하는 모든 이벤트는 동일한 identifier를 할당해야 합니다.

target

터치 포인트가 표면에 처음 놓였을 때 시작된 EventTarget입니다. 이후 해당 터치 포인트가 그 요소의 상호작용 영역 밖으로 이동했더라도 이 값은 처음 시작된 요소를 가리킵니다.

참고

일부 구현은 조잡한 입력(coarse input)의 부정확성을 보정하기 위해 대상 요소를 변경합니다. 따라서 대상 요소가 이벤트 좌표에 직접 있는 요소가 아닐 수도 있습니다. 조잡한 입력을 타깃팅/구분하는 데 사용되는 방법들은 이 명세서의 범위를 벗어납니다.

screenX

화면에 대한 점의 수평 좌표(픽셀 단위)

screenY

화면에 대한 점의 수직 좌표(픽셀 단위)

clientX

스크롤 오프셋을 제외한 뷰포트에 대한 점의 수평 좌표(픽셀 단위)

clientY

스크롤 오프셋을 제외한 뷰포트에 대한 점의 수직 좌표(픽셀 단위)

pageX

스크롤 오프셋을 포함한 뷰포트에 대한 점의 수평 좌표(픽셀 단위)

pageY

스크롤 오프셋을 포함한 뷰포트에 대한 점의 수직 좌표(픽셀 단위)

radiusX

rotationAngle로 표시된 축을 따라 접촉 영역(예: 손가락, 스타일러스)을 가장 가깝게 둘러싸는 타원의 반지름입니다. 단위는 screenX와 동일한 스케일의 CSS 픽셀([CSS-VALUES])입니다. 알려진 값이 없으면 0입니다. 값은 음수가 될 수 없습니다.

radiusY

rotationAngle로 표시된 축에 수직인 축을 따라 접촉 영역(예: 손가락, 스타일러스)을 가장 가깝게 둘러싸는 타원의 반지름입니다. 단위는 screenY와 동일한 스케일의 CSS 픽셀([CSS-VALUES])입니다. 알려진 값이 없으면 0입니다. 값은 음수가 될 수 없습니다.

rotationAngle

radiusX와 radiusY로 기술된 타원이 중심을 기준으로 시계 방향으로 회전한 각도(도 단위); 알려진 값이 없으면 0입니다. 값은 0 이상이고 90 미만이어야 합니다.

만약 radiusX와 radiusY로 기술된 타원이 원형이라면 rotationAngle은 영향을 주지 않습니다. 이 경우 사용자 에이전트는 0을 사용할 수 있으며, 또는 허용 범위 내의 다른 값을 사용할 수 있습니다. (예: 갑작스러운 변화를 피하기 위해 이전 터치 이벤트의 rotationAngle 값을 사용할 수 있습니다.)

force

적용된 압력의 상대 값으로, 범위는 0에서 1까지입니다. 여기서 0은 압력 없음, 1은 터치 장치가 감지할 수 있는 가장 높은 압력을 의미합니다. 알려진 값이 없으면 0입니다. force가 알려진 환경에서는 force 속성이 나타내는 절대 압력과 압력 민감도의 단계는 달라질 수 있습니다.

altitudeAngle

트랜스듀서(예: 펜/스타일러스)의 고도(라디안 단위)로, 범위는 [0,π/2]입니다 — 여기서 0은 표면(X-Y 평면)과 평행함을, π/2는 표면에 수직임을 뜻합니다. 기울기나 각도를 보고하지 않는 하드웨어나 플랫폼의 경우 값은 MUST 0이어야 합니다.

참고
여기서 정의한 altitudeAngle의 기본값은 0입니다. 이는 Pointer Events - Level 3 [POINTEREVENTS] 명세의 altitudeAngle 속성의 기본값(π/2, 트랜스듀서를 표면에 수직으로 위치시키는 값)과 다릅니다.
altitudeAngle 설명 다이어그램
그림 1 altitudeAngle이 π/4인 예 (X-Y 평면에서 45도).
azimuthAngle

트랜스듀서(예: 펜/스타일러스)의 방위각(라디안 단위)으로, 범위는 [0, 2π]입니다 — 여기서 0은 X 값이 증가하는 방향(정면에서 보았을 때 "3시 방향")을 가리키는 트랜스듀서를 나타내며, 값은 시계 방향으로 증가합니다(π/2는 "6시", π는 "9시", 3π/2는 "12시"). 트랜스듀서가 표면에 완전히 수직인 경우(altitudeAngle이 π/2) 값은 MUST 0이어야 합니다. 기울기나 각도를 보고하지 않는 하드웨어나 플랫폼의 경우 값은 MUST 0이어야 합니다.

azimuthAngle 설명 다이어그램
그림 2 azimuthAngle이 π/6인 예 ("4시" 방향).
touchType

터치를 유발한 장치의 유형입니다.

TouchType

가능한 터치 입력의 서로 다른 유형을 나타내는 열거형입니다.

direct

화면에 직접 닿는 손가락의 터치입니다.

stylus

스타일러스나 펜 장치의 터치입니다.

4. TouchList 인터페이스

이 인터페이스는 터치 이벤트를 위한 개별 접촉 지점의 목록을 정의합니다. TouchList 객체는 불변이며; 생성된 이후에는 그 내용이 변경되어서는 안 됩니다.

TouchList 객체의 지원되는 속성 인덱스([WEBIDL])는 목록의 길이보다 1 작은 값에서 0까지의 범위에 있는 숫자들입니다.

WebIDL[Exposed=Window]
interface TouchList {
    readonly        attribute unsigned long length;
    getter Touch? item (unsigned long index);
};
length

목록에 있는 Touch 객체의 수를 반환합니다.

item

목록에서 지정된 인덱스의 Touch를 반환하며, 인덱스가 목록의 길이보다 크거나 같으면 null을 반환합니다.

5. TouchEvent 인터페이스

이 인터페이스는 touchstart, touchend, touchmove, 및 touchcancel 이벤트 유형을 정의합니다. TouchEvent 객체는 불변이며; 생성 및 초기화된 이후에는 그 속성이 변경되어서는 안 됩니다. TouchEvent는 [DOM-LEVEL-3-EVENTS]에 정의된 UIEvent 인터페이스를 상속합니다.

TouchEventInit 딕셔너리는 TouchEvent 인터페이스의 생성자가 신뢰되지 않은(합성된) 터치 이벤트를 생성하기 위한 메커니즘을 제공하는 데 사용됩니다. 이 딕셔너리는 [DOM-LEVEL-3-EVENTS]에 정의된 EventModifierInit 딕셔너리를 상속합니다. 이벤트 생성 절차는 [DOM4]에 정의되어 있습니다. 신뢰되지 않은 터치 이벤트를 발생시키는 방법을 보여주는 샘플 코드는 예제를 참조하세요.

WebIDLdictionary TouchEventInit : EventModifierInit {
            sequence<Touch> touches = [];
            sequence<Touch> targetTouches = [];
            sequence<Touch> changedTouches = [];
};

[Exposed=Window]
interface TouchEvent : UIEvent {
    constructor(DOMString type, optional TouchEventInit eventInitDict = {});
    readonly        attribute TouchList touches;
    readonly        attribute TouchList targetTouches;
    readonly        attribute TouchList changedTouches;
    readonly        attribute boolean   altKey;
    readonly        attribute boolean   metaKey;
    readonly        attribute boolean   ctrlKey;
    readonly        attribute boolean   shiftKey;
    getter boolean getModifierState (DOMString keyArg);
};
touches

현재 표면에 접촉되어 있는 모든 접촉 지점에 대한 Touch 객체의 목록입니다.

targetTouches

현재 표면에 접촉되어 있고 그리고 현재 이벤트의 대상이 되는 요소에서 시작된 모든 접촉 지점에 대한 Touch 객체의 목록입니다.

changedTouches

이 이벤트에 기여한 모든 접촉 지점에 대한 Touch 객체의 목록입니다.

touchstart 이벤트의 경우, 이는 현재 이벤트로 활성화된 터치 포인트들의 목록이어야 합니다. touchmove 이벤트의 경우, 이는 마지막 이벤트 이후로 이동한 터치 포인트들의 목록이어야 합니다. touchendtouchcancel 이벤트의 경우, 이는 표면에서 제거된 터치 포인트들의 목록이어야 하며, 제거되기 전의 마지막 알려진 좌표를 포함해야 합니다.

altKey

alt(Alternate) 키 수정자가 활성화되어 있으면 true, 그렇지 않으면 false

metaKey

meta(Meta) 키 수정자가 활성화되어 있으면 true, 그렇지 않으면 false. 일부 플랫폼에서는 이 속성이 이름이 다른 키 수정자에 매핑될 수 있습니다.

ctrlKey

ctrl(Control) 키 수정자가 활성화되어 있으면 true, 그렇지 않으면 false

shiftKey

shift(Shift) 키 수정자가 활성화되어 있으면 true, 그렇지 않으면 false

getModifierState(keyArg)

키 값을 사용하여 수정자의 상태를 조회합니다. 해당 키가 수정자 키이고 그 수정자가 활성화되어 있으면 true, 그렇지 않으면 false를 반환합니다.

5.1 TouchEvent 구현자 메모

이 절은 비규범적입니다.

참고

사용자 에이전트는 주어진 Touch 객체들이 모두 해당 TouchEvent가 디스패치된 동일한 문서와 연관되도록 해야 합니다. 이를 구현하기 위해, 사용자 에이전트는 현재의 touch-active 문서 개념을 유지해야 합니다. 최초 터치 시 이것은 터치가 생성된 대상 문서로 설정됩니다. 모든 활성 터치 포인트가 해제되면 touch-active 문서는 지워집니다. 모든 TouchEvent는 현재의 touch-active 문서로 디스패치되며, 그 안에 포함된 각 Touch 객체는 해당 문서의 DOM 요소(및 좌표)만을 참조합니다. 터치가 완전히 현재의 touch-active 문서 바깥에서 시작된 경우, 해당 터치는 완전히 무시되어야 합니다.

5.2 사용 예제

이 절은 비규범적입니다.

아래 예제들은 TouchList 멤버들 간의 관계를 TouchEvent 내에서 어떻게 구성되는지 보여줍니다.

5.2.1 TouchEventtouchestargetTouches

이 예제는 TouchEvent 인터페이스에 정의된 touchestargetTouches 멤버들 간의 유용성과 관계를 보여줍니다. 아래 코드는 터치 가능한 요소 및 문서상의 터치 포인트 수에 따라 다른 출력을 생성합니다:

<div id="touchable">This element is touchable.</div>

<script>
document.getElementById('touchable').addEventListener('touchstart', function(ev) {

    if (ev.touches.item(0) == ev.targetTouches.item(0))
    {
        /**
         * If the first touch on the surface is also targeting the
         * "touchable" element, the code below should execute.
         * Since targetTouches is a subset of touches which covers the
         * entire surface, TouchEvent.touches >= TouchEvents.targetTouches
         * is always true.
         */

        document.write('Hello Touch Events!');
    }

    if (ev.touches.length == ev.targetTouches.length)
    {
        /**
         * If all of the active touch points are on the "touchable"
         * element, the length properties should be the same.
         */

        document.write('All points are on target element')
    }

    if (ev.touches.length > 1)
    {
        /**
         * On a single touch input device, there can only be one point
         * of contact on the surface, so the following code can only
         * execute when the terminal supports multiple touches.
         */

        document.write('Hello Multiple Touch!');
    }

}, false);
</script>

5.2.2 TouchEventchangedTouches

이 예제는 changedTouches의 유용성과 TouchList의 다른 멤버들과의 관계를 보여줍니다. 아래 코드는 정의된 터치 가능한 요소에서 터치 포인트가 제거될 때마다 트리거되는 예제입니다:

<div id="touchable">This element is touchable.</div>

<script>
document.getElementById('touchable').addEventListener('touchend', function(ev) {

    /**
     * Example output when three touch points are on the surface,
     * two of them being on the "touchable" element and one point
     * in the "touchable" element is lifted from the surface:
     *
     * Touch points removed: 1
     * Touch points left on element: 1
     * Touch points left on document: 2
     */

    document.write('Touch points removed: ' + ev.changedTouches.length);
    document.write('Touch points left on element: ' + ev.targetTouches.length);
    document.write('Touch points left on document: ' + ev.touches.length);

}, false);
</script>

5.2.3 스크립트에서 합성된 TouchEvent 발생시키기

이 예제는 스크립트에서 TouchEvent를 생성하고 발생시키는 방법을 보여줍니다.

if (Touch.length < 1 || TouchEvent.length < 1)
  throw "TouchEvent constructors not supported";

var touch = new Touch({
    identifier: 42,
    target: document.body,
    clientX: 200,
    clientY: 200,
    screenX: 300,
    screenY: 300,
    pageX: 200,
    pageY: 200,
    radiusX: 5,
    radiusY: 5
});

var touchEvent = new TouchEvent("touchstart", {
    cancelable: true,
    bubbles: true,
    composed: true,
    touches: [touch],
    targetTouches: [touch],
    changedTouches: [touch]
});

document.body.dispatchEvent(touchEvent);

5.3 TouchEvent 유형 목록

이 절은 비규범적입니다.

다음 표는 이 명세서에 정의된 TouchEvent 이벤트 유형들의 요약을 제공합니다. 모든 이벤트는 버블링 단계를 수행해야 합니다. 모든 이벤트는 구성된(composed) 이벤트여야 합니다 [WHATWG-DOM].

이벤트 유형 동기 / 비동기 버블링 단계 구성됨 신뢰된 근접 이벤트 대상 유형 인터페이스 취소 가능성 기본 동작
touchstart 동기 Document, Element TouchEvent 상황에 따라 정의되지 않음
touchend 동기 Document, Element TouchEvent 상황에 따라 상황에 따라: 사용자 에이전트는 마우스 및 클릭 이벤트를 디스패치할 수 있습니다
touchmove 동기 Document, Element TouchEvent 상황에 따라 정의되지 않음
touchcancel 동기 Document, Element TouchEvent 아니오 없음

5.4 터치 이벤트의 취소 가능성

터치 이벤트를 취소하면 스크롤을 방지하거나 중단할 수 있습니다(스크롤은 스크립트 실행과 병행하여 발생할 수 있음). 최대 스크롤 성능을 위해, 사용자 에이전트는 스크롤과 관련된 각 터치 이벤트가 취소되는지를 확인하기 위해 모든 터치 이벤트가 처리될 때까지 기다리지 않을 수 있습니다. 이러한 경우 사용자 에이전트는 해당 이벤트의 cancelable 속성이 false인 터치 이벤트를 생성해야 하며, 이는 preventDefault를 사용하여 스크롤을 방지하거나 중단할 수 없음을 나타냅니다. 그렇지 않으면 cancelabletrue가 됩니다.

특히, 사용자 에이전트는 이벤트에 대해 비수동(non-passive) 리스너가 없음을 관찰할 때 취소할 수 없는 터치 이벤트만 생성해야 합니다.

5.5 touchstart 이벤트

사용자 에이전트는 사용자가 터치 표면에 터치 포인트를 놓을 때 이 이벤트 유형을 디스패치해야 합니다.

이 이벤트의 대상은 Element여야 합니다. 터치 포인트가 프레임 내에 있는 경우, 이벤트는 해당 프레임의 자식 브라우징 컨텍스트에 있는 요소에 디스패치되어야 합니다.

이 이벤트가 취소된 경우, 동일한 활성 터치 포인트와 관련된 모든 터치 이벤트로 인해 발생하는 기본 동작(마우스 이벤트나 스크롤 포함)을 방지해야 합니다.

5.6 touchend 이벤트

사용자 에이전트는 사용자가 터치 표면에서 터치 포인트를 제거할 때, 표면에서 물리적으로 벗어나는 경우(예: 화면 밖으로 드래그되는 경우)를 포함하여 이 이벤트 유형을 디스패치해야 합니다.

이 이벤트의 대상은 터치 포인트가 처음 표면에 놓였을 때 시작된 동일한 Element여야 하며, 이후 터치 포인트가 대상 요소의 상호작용 영역 밖으로 이동했더라도 동일해야 합니다.

제거된 터치 포인트는 changedTouches 속성에 포함되어야 하며, touchestargetTouches 속성에는 포함되어서는 안 됩니다.

이 이벤트가 취소된 경우, 이 이벤트를 포함하는 어떤 터치 이벤트 시퀀스도 클릭으로 해석되어서는 안 됩니다.

5.7 touchmove 이벤트

사용자 에이전트는 사용자가 터치 표면을 따라 터치 포인트를 이동할 때 이 이벤트 유형을 디스패치해야 합니다.

이 이벤트의 대상은 터치 포인트가 처음 표면에 놓였을 때 시작된 동일한 Element여야 하며, 이후 터치 포인트가 대상 요소의 상호작용 영역 밖으로 이동했더라도 동일해야 합니다.

touchmove 이벤트를 보내는 빈도는 구현에 따라 정의되며 하드웨어 능력 및 기타 구현 세부사항에 따라 달라질 수 있음을 유의하세요.

사용자 에이전트는 동일한 활성 터치 포인트와 관련된 적어도 하나의 touchmove 이벤트가 취소되지 않을 때까지 어떤 touchmove 이벤트로 인해 발생하는 기본 동작을 억제해야 합니다. 동일한 활성 터치 포인트와 관련된 적어도 하나의 touchmove 이벤트가 취소되지 않은 이후에 touchmove 이벤트들의 기본 동작이 억제되는지는 구현에 따라 다릅니다.

5.8 touchcancel 이벤트

사용자 에이전트는 동작이 구현 특유의 방식으로 중단될 때(예: UA에서 발생한 동기 이벤트나 동작이 터치를 취소하는 경우, 또는 터치 포인트가 문서 창을 벗어나 사용자 상호작용을 처리할 수 있는 비문서 영역(예: UA의 네이티브 UI나 플러그인에 의해 관리되는 문서의 영역)으로 들어가는 경우) 이 이벤트 유형을 디스패치해야 합니다. 또한 사용자가 터치 표면에 장치나 구현이 저장하도록 구성된 것보다 더 많은 터치 포인트를 놓은 경우, 이 이벤트 유형을 디스패치할 수 있으며 이 경우 Touch 객체 목록에서 가장 초기의 항목이 제거되어야 합니다.

이 이벤트의 대상은 터치 포인트가 처음 표면에 놓였을 때 시작된 동일한 Element여야 하며, 이후 터치 포인트가 대상 요소의 상호작용 영역 밖으로 이동했더라도 동일해야 합니다.

제거된 터치 포인트는 changedTouches 속성에 포함되어야 하며, touchestargetTouches 속성에는 포함되어서는 안 됩니다.

6. 재타겟팅

다음 절은 [WHATWG-DOM]에 정의된 재타겟팅 단계를 설명합니다.

Touch 객체에는 연관된 unadjustedTarget(null 또는 EventTarget)이 있습니다. 달리 명시되지 않는 한 이것은 null입니다.

TouchEvent재타겟팅 단계는, touchEvent가 주어졌을 때, 다음 단계를 실행해야 합니다:

  1. touchEventtouches, targetTouches, 및 changedTouches 멤버에 있는 각 Touch touch에 대해:

    1. 만약 touchunadjustedTarget이 null이면, touchunadjustedTargettouchtarget으로 설정합니다.
    2. touchtarget을, 재타겟팅을 호출하여 touchunadjustedTargettouchEventtarget에 대해 재타겟팅한 결과로 설정합니다.

7. 레거시 터치 이벤트 API 조건부 노출

사용자 에이전트에는 불리언 값인 expose legacy touch event APIs가 연결되어 있으며, 그 값은 구현 정의적(implementation-defined)입니다.

참고

기존 웹 콘텐츠는 종종 이러한 API의 존재를 사용자 에이전트가 터치 가능 "모바일" 장치임을 나타내는 신호로 사용합니다. 따라서 비모바일 장치(터치 가능하더라도)에서 이러한 API를 노출하면 해당 웹 콘텐츠에 대해 최적이 아닌 사용자 경험으로 이어질 수 있습니다.

8. GlobalEventHandlers 믹스인에 대한 확장

다음 절은 이벤트 핸들러 등록을 용이하게 하기 위해 [HTML5]에 정의된 기존 GlobalEventHandlers 믹스인에 대한 확장을 설명합니다. expose legacy touch event APIs가 false인 사용자 에이전트에서는 이 믹스인을 구현해서는 안 됩니다.

WebIDLpartial interface mixin GlobalEventHandlers {
                    attribute EventHandler ontouchstart;
                    attribute EventHandler ontouchend;
                    attribute EventHandler ontouchmove;
                    attribute EventHandler ontouchcancel;
};
ontouchstart

touchstart 이벤트 유형에 대한 이벤트 핸들러 IDL 속성입니다(자세한 내용은 [HTML5] 참조).

ontouchend

touchend 이벤트 유형에 대한 이벤트 핸들러 IDL 속성입니다(자세한 내용은 [HTML5] 참조).

ontouchmove

touchmove 이벤트 유형에 대한 이벤트 핸들러 IDL 속성입니다(자세한 내용은 [HTML5] 참조).

ontouchcancel

touchcancel 이벤트 유형에 대한 이벤트 핸들러 IDL 속성입니다(자세한 내용은 [HTML5] 참조).

9. 마우스 이벤트 및 click과의 상호작용

사용자 에이전트는 동일한 사용자 입력에 대해 터치 이벤트와(터치용으로 설계되지 않은 웹 콘텐츠와의 호환성을 위해) 마우스 이벤트 [DOM-LEVEL-2-EVENTS]를 모두 디스패치할 수 있습니다. 만약 사용자 에이전트가 단일 사용자 동작에 대해 터치 이벤트와 마우스 이벤트를 모두 디스패치한다면, 그 동작에 대한 어떤 마우스 이벤트보다 먼저 touchstart 이벤트 유형이 디스패치되어야 합니다. 또한 touchstart, touchmove 또는 touchend취소된 경우, 사용자 에이전트는 그 취소된 터치 이벤트로 인해 발생할 수 있는 결과적인 어떤 마우스 이벤트도 디스패치해서는 안 됩니다.

참고

웹 애플리케이션이 터치 이벤트를 처리할 수 있다면, 해당 이벤트를 취소할 수 있으며, 그에 따라 대응하는 마우스 이벤트를 사용자 에이전트가 디스패치할 필요가 없을 수 있습니다. 반면 웹 애플리케이션이 터치 입력 장치용으로 특별히 작성되지 않았다면, 이후에 발생하는 마우스 이벤트에 반응할 것입니다.

참고

사용자 에이전트는 일반적으로 단일 손가락 활성화 제스처(예: 탭 및 롱프레스)에 대해서만 마우스 및 클릭 이벤트를 디스패치합니다. 터치 포인트의 이동이 수반되거나 두 개 이상의 활성 터치 포인트가 있는 멀티터치 상호작용의 경우에는 보통 터치 이벤트만 생성됩니다.

만약 사용자 에이전트가 터치 이벤트 시퀀스를 탭 제스처로 해석한다면, 해당 터치 입력과 대응하는 touchend 이벤트 위치에서 mousemove, mousedown, mouseup, 및 click 이벤트(이 순서대로)를 디스패치해야 합니다. 터치 이벤트 처리 중 문서의 내용이 변경된 경우, 사용자 에이전트는 마우스 이벤트를 터치 이벤트와 다른 대상에 디스패치할 수 있습니다.

추가적인 터치 및 마우스 이벤트의 기본 동작과 순서는 다른 곳에 명시된 경우를 제외하고는 구현 정의적입니다.

참고

요소의 활성화(예: 일부 구현에서의 탭)는 일반적으로 다음과 같은 이벤트 시퀀스를 생성합니다(구현별 동작에 따라 약간 다를 수 있음):

  1. touchstart
  2. 손가락의 이동에 따라 0개 이상의 touchmove 이벤트
  3. touchend
  4. mousemove (레거시 마우스 전용 코드와의 호환성 목적)
  5. mousedown
  6. mouseup
  7. click

하지만 상호작용 중 touchstart, touchmove 또는 touchend 이벤트가 취소된 경우에는 마우스나 클릭 이벤트가 발생하지 않으며, 결과적인 이벤트 시퀀스는 단순히 다음과 같습니다:

  1. touchstart
  2. 손가락의 이동에 따라 0개 이상의 touchmove 이벤트
  3. touchend
참고

사용자 에이전트가 Touch Events를 지원한다고 해서 터치스크린만 유일한 입력 수단인 것은 아닙니다. 특히 터치 가능 노트북이나 외부 입력 장치가 연결된 전통적인 "터치 전용" 장치(예: 휴대폰 및 태블릿)의 경우, 사용자는 터치스크린을 트랙패드, 마우스 또는 키보드와 함께 사용할 수 있습니다. 따라서 개발자는 "터치 OR 마우스/키보드"와 같은 조건부 바인딩을 피해야 합니다. 이는 터치 전용 사이트/애플리케이션을 만들 수 있어 다른 입력 수단을 사용하는 사용자를 배제하게 됩니다.


// conditional "touch OR mouse/keyboard" event binding
// DON'T DO THIS, as it makes interactions touch-exclusive
// on devices that have both touch and mouse/keyboard

if ('ontouchstart' in window) {
  // set up event listeners for touch
  target.addEventListener('touchend', ...);
  ...
} else {
  // set up event listeners for mouse/keyboard
  target.addEventListener('click', ...);
  ...
}

대신 개발자는 서로 다른 입력 형태를 동시에 처리해야 합니다.


// concurrent "touch AND mouse/keyboard" event binding

// set up event listeners for touch
target.addEventListener('touchend', function(e) {
  // prevent compatibility mouse events and click
  e.preventDefault();
  ...
});
...

// set up event listeners for mouse/keyboard
target.addEventListener('click', ...);
...

터치와 호환성 마우스 이벤트(터치 이벤트에 의해 생성된)를 두 번 처리하지 않도록 하려면, 개발자는 터치 이벤트를 취소하여 추가적인 마우스나 클릭 이벤트의 생성을 억제해야 합니다. 또는 InputDeviceCapabilities API를 사용하여 터치 이벤트로 인해 생성된 마우스 이벤트를 감지하는 방법을 사용할 수 있습니다.

10. 용어집

활성 터치 포인트
현재 화면에 있으며 사용자 에이전트가 추적하고 있는 터치 포인트입니다. 터치 포인트는 사용자 에이전트가 그 출현을 나타내는 touchstart 이벤트를 처음 디스패치할 때 활성화됩니다. 터치 포인트는 사용자 에이전트가 표면에서 제거되었거나 더 이상 추적되지 않음을 나타내는 touchend 또는 touchcancel 이벤트를 디스패치한 후 활성 상태가 해제됩니다.
터치 포인트
포인터(예: 손가락 또는 스타일러스)가 인터페이스의 대상 표면과 교차하는 좌표 지점입니다. 이는 터치스크린에 손가락이 닿는 경우나 디지털 펜이 종이에 글을 쓸 때에 해당할 수 있습니다.
취소된 이벤트
기본 동작이 preventDefault()로 방지되었거나, 이벤트 핸들러에서 false를 반환했거나, [DOM-LEVEL-3-EVENTS] 및 [HTML5]에서 정의된 다른 수단으로 방지된 이벤트입니다.

A. 감사의 글

이 절은 비규범적입니다.

이 명세의 기반으로 사용된 모델을 개발한 WebKit 엔지니어들에게 감사드리며, WebKit 터치 이벤트 요약을 제공한 Neil Roberts (SitePen), 기고와 제안을 해주신 Peter-Paul Koch (PPK), ReSpec.js 명세 작성 도구를 개발한 Robin Berjon, 그리고 많은 기여를 해준 WebEvents WG에 감사드립니다.

명세가 발전하는 동안 추가 의견을 주신 많은 분들 덕분에 지속적인 개선이 이루어졌습니다. 그 중에는 Matthew Schinckel, Andrew Grieve, Cathy Chan, Boris Zbarsky, Patrick H. Lauke, Simon Pieters 등이 포함됩니다. 만약 의도치 않게 귀하의 이름을 빠뜨렸다면 알려주시기 바랍니다.

이 명세의 테스트 스위트에 기여한 다음의 기여자들에게 감사드립니다: Matt Brubeck, Olli Pettay, Art Barstow, Cathy Chan 및 Rick Byers.

B. 이전 게시 이후 변경 사항

이 절은 비규범적입니다.

이는 2013년 10월 10일 권고문이 게시된 이후 이루어진 주요 변경 사항들의 요약입니다. 전체 커밋 기록은 여기에서 확인할 수 있습니다.

C. 참조

C.1 규범 참조

[CSS-VALUES]
CSS Values and Units Module Level 3. Tab Atkins Jr.; Elika Etemad. W3C. 2024년 3월 22일. W3C 후보 권고. URL: https://www.w3.org/TR/css-values-3/
[DOM-LEVEL-2-EVENTS]
Document Object Model (DOM) Level 2 Events Specification. Tom Pixley. W3C. 2020년 11월 3일. W3C 권고. URL: https://www.w3.org/TR/DOM-Level-2-Events/
[DOM-LEVEL-3-EVENTS]
UI Events. Gary Kacmarcik; Travis Leithead. W3C. 2024년 6월 22일. W3C 작업 초안. URL: https://www.w3.org/TR/uievents/
[DOM4]
DOM Standard. Anne van Kesteren. WHATWG. 현행 표준. URL: https://dom.spec.whatwg.org/
[html]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[HTML5]
HTML5. Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia Pfeiffer. W3C. 2018년 3월 27일. W3C 권고. URL: https://www.w3.org/TR/html5/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. 현행 표준. URL: https://webidl.spec.whatwg.org/

C.2 정보 참조

[POINTEREVENTS]
Pointer Events. Jacob Rossi; Matt Brubeck. W3C. 2019년 4월 4일. W3C 권고. URL: https://www.w3.org/TR/pointerevents/