포인터 이벤트

레벨 4

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-pointerevents4-20261008/
최신 공개 버전:
https://www.w3.org/TR/pointerevents4/
최신 편집자 초안:
https://w3c.github.io/pointerevents/
이력:
https://www.w3.org/standards/history/pointerevents4/
커밋 이력
테스트 모음:
https://wpt.fyi/pointerevents/
최신 권고안:
https://www.w3.org/TR/pointerevents3
편집자:
Patrick H. Lauke (TetraLogical)
Robert Flack (Google)
이전 편집자:
Matt Brubeck (Mozilla)
Rick Byers (Google)
Navid Zolghadr (Google)
피드백:
GitHub w3c/pointerevents (풀 리퀘스트, 새 이슈, 열린 이슈)
public-pointer-events@w3.org 로 제목 줄에 [pointerevents4] … 메시지 주제 …를 사용하여 보내십시오 (아카이브)
브라우저 지원:
caniuse.com

초록

Pointer Events 명세는 마우스, 터치스크린, 펜/스타일러스 등 다양한 장치의 입력을 처리하기 위한 통합된 하드웨어 독립적 프레임워크를 정의한다. 단일 이벤트 집합(예: pointerdown, pointermove, pointerup)을 제공함으로써 개발자가 각 장치별 논리를 작성하지 않고도 다양한 입력 방식을 지원할 수 있도록 한다.

이 명세는 Mouse 및 Wheel 이벤트와 다른 포인터 장치 유형에 대해 Mouse 이벤트를 발생시키기 위한 매핑도 정의한다.

이 문서의 상태

이 절에서는 이 문서가 공개된 시점의 상태를 설명한다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있다.

이 명세는 [PointerEvents3] 명세의 업데이트이다. 또한 이전에 [UIEVENTS] 명세에 있던 Mouse 및 Wheel 이벤트를 포함한다.

이번 개정판에는 다음과 같은 새로운 기능이 포함된다:

이 문서는 Pointer Events 작업 그룹이 권고안 트랙을 사용하여 작업 초안으로 공개했다.

작업 초안으로 공개되었다고 해서 W3C 및 그 회원들이 이를 승인한다는 의미는 아니다.

이 문서는 초안이며 언제든지 다른 문서에 의해 업데이트, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 해당 그룹의 결과물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지한다. 해당 페이지에는 특허를 공개하기 위한 지침도 포함되어 있다. 자신이 필수 청구항을 포함한다고 판단하는 특허를 실제로 알고 있는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받는다.

1. 소개

이 섹션은 비규범적이다.

오늘날 대부분의 [HTML] 콘텐츠는 마우스 입력과 함께 사용되거나 마우스 입력을 위해 설계된다. 입력을 사용자 정의 방식으로 처리하는 콘텐츠는 일반적으로 Mouse 이벤트에 맞춰 코드를 작성한다. 그러나 오늘날의 최신 컴퓨팅 장치는 터치스크린과 펜 입력을 비롯한 다른 형태의 입력도 포함한다. 이러한 각 입력 형태를 개별적으로 처리하기 위한 이벤트 유형이 제안되어 왔다. 그러나 이러한 접근 방식은 새로운 입력 유형에 대한 지원을 추가할 때 불필요한 논리 중복과 이벤트 처리 오버헤드를 발생시키는 경우가 많다. 또한 콘텐츠가 하나의 장치 유형만을 염두에 두고 작성되면 호환성 문제가 발생하는 경우가 많다. 또한 기존의 마우스 기반 콘텐츠와의 호환성을 위해 대부분의 사용자 에이전트는 모든 입력 유형에 대해 Mouse 이벤트를 발생시킨다. 이로 인해 Mouse 이벤트가 실제 마우스 장치를 나타내는 것인지, 아니면 호환성을 위해 다른 입력 유형에서 생성된 것인지가 모호해져 두 장치 유형을 동시에 처리하는 코드를 작성하기 어려워진다.

여러 입력 유형을 처리하기 위한 코딩 비용을 줄이고 위에서 설명한 Mouse 이벤트의 모호성을 해결하기 위해 이 명세에서는 포인터라고 하는 보다 추상적인 형태의 입력을 정의한다. 포인터는 마우스 커서, 펜, 터치(멀티터치 포함) 또는 기타 포인팅 입력 장치가 화면에 만드는 모든 접촉점일 수 있다. 이 모델을 사용하면 사용자가 어떤 하드웨어를 가지고 있든 잘 작동하는 사이트와 애플리케이션을 더 쉽게 작성할 수 있다. 장치별 처리가 필요한 경우를 위해 이 명세에서는 이벤트를 생성한 장치 유형을 검사하기 위한 속성도 정의한다. 주요 목표는 장치 간 포인터 입력을 더 쉽게 작성할 수 있게 하는 단일 이벤트 및 인터페이스 집합을 제공하는 동시에, 향상된 경험을 위해 필요한 경우에만 장치별 처리를 허용하는 것이다.

또 다른 주요 목표는 멀티스레드 사용자 에이전트가 직접 조작 방식의 패닝 및 확대/축소 동작(예: 터치스크린에서 손가락이나 스타일러스를 사용하는 경우)을 스크립트 실행을 차단하지 않고 처리할 수 있도록 하는 것이다.

참고

이 명세에서는 다양한 포인터 입력을 위한 통합 이벤트 모델을 정의하지만, 이 모델은 키보드 또는 키보드와 유사한 인터페이스와 같은 다른 형태의 입력은 다루지 않는다(예를 들어, 터치스크린 전용 장치에서 실행되며 사용자가 포커스 가능한 컨트롤과 요소를 순차적으로 탐색할 수 있게 하는 스크린 리더 또는 이와 유사한 보조 기술). 사용자 에이전트가 이러한 인터페이스에 대한 응답으로 포인터 이벤트도 생성하도록 선택할 수 있지만, 이러한 시나리오는 이 명세에서 다루지 않는다.

우선 저자는 focus, blur 및 click과 같은 상위 수준 이벤트에 응답하여 모든 형태의 입력에 대해 동등한 기능을 제공하도록 권장된다. 그러나 저수준 이벤트(예: Pointer 이벤트)를 사용할 때 저자는 모든 유형의 입력이 지원되도록 하는 것이 권장된다. 키보드 및 키보드와 유사한 인터페이스의 경우 명시적인 키보드 이벤트 처리를 추가해야 할 수도 있다. 자세한 내용은 키보드 접근성 [WCAG22]을 참조한다.

포인터 입력은 마우스, 펜, 터치와 같은 다양한 입력 소스를 결합한다
그림 1 포인터는 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치의 하드웨어 독립적 표현이다.

일반적인 포인터 입력을 처리하기 위한 이벤트는 마우스용 이벤트와 매우 유사하다: pointerdown, pointermove, pointerup, pointerover, pointerout 등이 있다. 이를 통해 콘텐츠를 Mouse 이벤트에서 Pointer 이벤트로 쉽게 마이그레이션할 수 있다. Pointer 이벤트는 Mouse 이벤트에 존재하는 일반적인 모든 속성(클라이언트 좌표, 대상 요소, 버튼 상태 포함)뿐만 아니라 압력, 접촉 형상, 기울기와 같은 다른 형태의 입력을 위한 새로운 속성도 제공한다. 저자는 적절한 경우 서로 다른 입력 유형 간에 논리를 공유하도록 Pointer 이벤트에 맞춰 코드를 쉽게 작성할 수 있으며, 최상의 경험을 얻기 위해 필요한 경우에만 특정 입력 유형에 맞게 사용자 정의할 수 있다.

Pointer 이벤트는 다양한 입력 장치에서 발생하지만, 다른 장치별 이벤트 집합으로부터 생성되는 것으로 정의되지 않는다. 호환성을 위해 그렇게 하는 것이 가능하며 권장되지만, 이 명세는 다른 장치별 이벤트(예: 마우스 이벤트 또는 터치 이벤트)의 지원을 요구하지 않는다. 사용자 에이전트는 다른 어떤 장치 이벤트도 지원하지 않고 포인터 이벤트만 지원할 수 있다. 마우스별 이벤트를 대상으로 작성된 콘텐츠와의 호환성을 위해 이 명세에서는 마우스 이외의 장치에서 발생하는 포인터 입력을 기반으로 호환성 마우스 이벤트를 생성하는 방법을 설명하는 선택적 섹션을 제공한다.

참고

이 명세는 Touch 이벤트([TOUCH-EVENTS]에서 정의됨)와 Pointer 이벤트를 모두 지원하는 사용자 에이전트의 예상 동작에 대한 어떠한 조언도 제공하지 않는다. 이 두 명세 간의 관계에 대한 자세한 내용은 Touch Events 커뮤니티 그룹을 참조한다.

2. 적합성

비규범적으로 표시된 섹션뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적이다. 이 명세의 그 밖의 모든 내용은 규범적이다.

이 문서에서 핵심어 MAY, MUST, MUST NOT, OPTIONAL 및 SHOULD는 여기에서와 같이 모두 대문자로 표시되는 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 한다.

3. 포인터 이벤트 및 인터페이스

3.1 PointerEvent 인터페이스

WebIDLdictionary PointerEventInit : MouseEventInit {
    long        pointerId = 0;
    double      width = 1;
    double      height = 1;
    float       pressure = 0;
    float       tangentialPressure = 0;
    long        tiltX;
    long        tiltY;
    long        twist = 0;
    double      altitudeAngle;
    double      azimuthAngle;
    DOMString   pointerType = "";
    boolean     isPrimary = false;
    long        persistentDeviceId = 0;
    sequence<PointerEvent> coalescedEvents = [];
    sequence<PointerEvent> predictedEvents = [];
};

[Exposed=Window]
interface PointerEvent : MouseEvent {
    constructor(DOMString type, optional PointerEventInit eventInitDict = {});
    readonly        attribute long        pointerId;
    readonly        attribute double      width;
    readonly        attribute double      height;
    readonly        attribute float       pressure;
    readonly        attribute float       tangentialPressure;
    readonly        attribute long        tiltX;
    readonly        attribute long        tiltY;
    readonly        attribute long        twist;
    readonly        attribute double      altitudeAngle;
    readonly        attribute double      azimuthAngle;
    readonly        attribute DOMString   pointerType;
    readonly        attribute boolean     isPrimary;
    readonly        attribute long        persistentDeviceId;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};
pointerId

이벤트를 발생시키는 포인터의 고유 식별자. 사용자 에이전트는 주 마우스 포인터에 대해 일반적인 pointerId 값으로 0 또는 1을 예약할 수 있다. pointerId 값 -1은 포인팅 장치가 아닌 다른 것에 의해 생성된 이벤트를 나타내기 위해 예약하고 사용해야 한다. 그 밖의 모든 포인터에 대해 사용자 에이전트는 pointerId 값을 할당하는 방식에 서로 다른 전략과 접근 방식을 자유롭게 구현할 수 있다. 그러나 최상위 브라우징 컨텍스트([HTML]에서 정의됨)의 모든 활성 포인터는 고유해야 하며, 식별자는 다른 어떤 최상위 브라우징 컨텍스트의 영향도 받아서는 안 된다(즉, 하나의 최상위 브라우징 컨텍스트는 포인터가 해당 브라우징 컨텍스트 밖으로 이동하여 다른 최상위 브라우징 컨텍스트로 들어갈 때 포인터의 pointerId가 동일할 것이라고 가정할 수 없다).

사용자 에이전트는 이전 활성 포인터에서 더 이상 사용되지 않는 pointerId 값을 재사용할 수 있으며, 특정 포인팅 장치에 대해 항상 동일한 pointerId를 재사용할 수도 있다(예를 들어 다중 사용자 협업 애플리케이션에서 특정 사용자의 특정 펜/스타일러스 입력을 고유하게 식별하기 위해). 그러나 후자의 경우 서로 다른 페이지나 도메인에 걸친 핑거프린팅 및 추적 가능성을 최소화하기 위해 pointerId는 페이지/세션의 수명 동안에만 해당 특정 포인팅 장치와 명시적으로 연결해야 하며, 해당 특정 포인팅 장치를 새 세션에서 다시 사용할 때는 새로 무작위화된 pointerId를 선택해야 한다.

참고

pointerId 선택 알고리즘은 구현별로 다르다. 저자는 값이 다른 모든 활성 포인터와 구별되는 포인터의 식별자라는 것 이외에 특정 의미를 전달한다고 가정할 수 없다. 예를 들어 사용자 에이전트는 활성화되는 순서대로 모든 활성 포인터에 0부터 시작하는 숫자를 단순히 할당할 수 있지만, 이러한 값이 단조 증가한다고 보장되지는 않는다. 특정 포인팅 장치에 동일한 pointerId를 재사용할지 여부는 각 구현에 맡겨져 있으므로, 저자는 이에 의존하지 않는 것이 강력히 권장되며 대신 persistentDeviceId를 참조하는 것이 좋다.

width

포인터의 접촉 형상의 너비(X축 방향 크기)를 CSS 픽셀 단위로 나타낸 값([CSS21] 참조). 이 값은 주어진 포인터의 각 이벤트에서 갱신될 수 있다. 일반적으로 접촉 형상이 없는 입력 (예: 전통적인 마우스)과 입력의 실제 형상이 하드웨어에서 감지되지 않는 경우 사용자 에이전트는 기본값 1을 반환해야 한다.

height

포인터의 접촉 형상의 높이(Y축 방향 크기)를 CSS 픽셀 단위로 나타낸 값([CSS21] 참조). 이 값은 주어진 포인터의 각 이벤트에서 갱신될 수 있다. 일반적으로 접촉 형상이 없는 입력 (예: 전통적인 마우스)과 입력의 실제 형상이 하드웨어에서 감지되지 않는 경우 사용자 에이전트는 기본값 1을 반환해야 한다.

pressure

[0,1] 범위로 정규화된 포인터 입력의 압력으로, 0과 1은 각각 하드웨어가 감지할 수 있는 최소 및 최대 압력을 나타낸다. 압력을 지원하지 않는 하드웨어 및 플랫폼에서는 활성 버튼 상태일 때 값이 0.5이어야 하며, 그렇지 않을 때는 0이어야 한다.

tangentialPressure

일반적으로 추가 컨트롤(예: 에어브러시 스타일러스의 핑거 휠)에 의해 설정되는 포인터 입력의 정규화된 접선 압력(배럴 압력이라고도 함)으로, [-1,1] 범위이며 0은 컨트롤의 중립 위치이다. 일부 하드웨어는 [0,1] 범위의 양수 값만 지원할 수 있음에 유의한다. 접선 압력을 지원하지 않는 하드웨어 및 플랫폼의 경우 값은 반드시 0이어야 한다.

참고
속성 이름과 달리 실제로 이 속성의 값을 생성하는 하드웨어 컨트롤/센서가 반드시 압력에 민감한 것은 아니다. 예를 들어 대부분의 에어브러시/페인팅 스타일러스 구현에서 핑거 휠은 사용자가 휠이 0 위치로 되돌아가는 것을 방지하기 위해 일정한 압력을 가할 필요 없이 자유롭게 설정할 수 있다.
tiltX

Y-Z 평면과 트랜스듀서(예: 펜/스타일러스) 축 및 Y축을 모두 포함하는 평면 사이의 평면각(도 단위, [-90,90] 범위)이다. 양의 tiltX는 X 값이 증가하는 방향인 오른쪽이다. tiltX는 tiltY와 함께 사용하여 디지타이저에 대한 트랜스듀서의 법선에서 벗어난 기울기를 나타낼 수 있다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 반드시 0이어야 한다.

tiltX 설명 다이어그램
그림 2 양의 tiltX.
tiltY

X-Z 평면과 트랜스듀서(예: 펜/스타일러스) 축 및 X축을 모두 포함하는 평면 사이의 평면각(도 단위, [-90,90] 범위)이다. 양의 tiltY는 Y 값이 증가하는 방향인 사용자 쪽이다. tiltY는 tiltX와 함께 사용하여 디지타이저에 대한 트랜스듀서의 법선에서 벗어난 기울기를 나타낼 수 있다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 반드시 0이어야 한다.

tiltY 설명 다이어그램
그림 3 양의 tiltY.
twist

트랜스듀서(예: 펜/스타일러스)가 자체 주축을 중심으로 시계 방향으로 회전한 정도 (도 단위, [0,359] 범위)이다. twist를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 반드시 0이어야 한다.

altitudeAngle

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

참고
여기서 altitudeAngle에 대해 정의된 기본값은 π/2이며, 이는 트랜스듀서가 표면에 수직으로 위치함을 나타낸다. 이는 기본값이 0인 Touch Events - Level 2 명세의 altitudeAngle 속성 정의와 다르다.
altitudeAngle 설명 다이어그램
그림 4 π/4인 altitudeAngle의 예(X-Y 평면으로부터 45도).
azimuthAngle

트랜스듀서(예: 펜/스타일러스)의 방위각(라디안 단위)으로, [0, 2π] 범위이다. 여기서 0은 X-Y 평면에서 트랜스듀서의 캡이 X 값이 증가하는 방향을 가리키는 상태(수직으로 내려다보았을 때 "3시" 방향)를 나타내며, 시계 방향으로 갈수록 값이 점진적으로 증가한다(π/2는 "6시", π는 "9시", 3π/2는 "12시"). 트랜스듀서가 표면에 완전히 수직일 때(altitudeAngle이 π/2) 값은 반드시 0이어야 한다. 기울기나 각도를 보고하지 않는 하드웨어 및 플랫폼의 경우 값은 반드시 0이어야 한다.

azimuthAngle 설명 다이어그램
그림 5 π/6인 azimuthAngle의 예("4시").
pointerType

이벤트를 발생시킨 장치 유형(예: 마우스, 펜, 터치)을 나타낸다. 사용자 에이전트가 마우스, 펜/스타일러스 또는 터치 입력 장치에 대해 포인터 이벤트를 발생시키는 경우 pointerType 값은 반드시 다음 표를 따라야 한다:

포인터 장치 유형 pointerType 값
마우스 mouse
펜 / 스타일러스 pen
터치 접촉 touch

사용자 에이전트가 장치 유형을 감지할 수 없는 경우 값은 반드시 빈 문자열이어야 한다. 사용자 에이전트가 위에 나열된 것 이외의 포인터 장치 유형을 지원하는 경우 서로 다른 장치 유형의 이름 충돌을 방지하기 위해 pointerType 값에 공급업체 접두사를 붙이는 것이 좋다. 향후 명세에서 다른 장치 유형에 대해 추가적인 규범적 값을 제공할 수 있다.

참고
pointerType을 사용하는 방법의 기본적인 예는 예제 2를 참조한다. 또한 개발자는 자체 사용자 정의 pointerType 값을 구현했을 수 있는 사용자 에이전트와 pointerType이 단순히 빈 문자열인 상황을 처리할 수 있도록 어떤 형태로든 기본 처리를 포함해야 한다.
isPrimary

포인터가 이 포인터 유형의 주 포인터를 나타내는지 여부를 나타낸다.

persistentDeviceId

포인팅 장치의 고유 식별자. 하드웨어가 여러 포인터를 지원하는 경우, 포인팅 장치에서 생성된 포인터 이벤트는 해당 포인터를 세션 전체에서 고유하게 식별할 수 있는 경우에만 persistentDeviceId를 가져야 한다. 포인터를 고유하게 식별할 수 있는 경우 해당 포인팅 장치에 할당된 persistentDeviceId는 세션의 나머지 기간 동안 일정하게 유지된다. persistentDeviceId 값 0은 이벤트를 생성한 장치를 식별할 수 없는 경우를 나타내기 위해 예약하고 사용해야 한다. pointerId와 마찬가지로 서로 다른 페이지나 도메인에 걸친 핑거프린팅 및 추적 가능성을 최소화하기 위해 persistentDeviceId는 페이지/세션의 수명 동안에만 해당 특정 포인팅 장치와 명시적으로 연결해야 하며, 해당 특정 포인팅 장치를 새 세션에서 다시 사용할 때는 새로 무작위화된 persistentDeviceId를 선택해야 한다.

참고
디지타이저 및 포인팅 장치 하드웨어의 제약으로 인해 포인팅 장치의 모든 포인터 이벤트에 persistentDeviceId를 사용할 수 있다고 보장되지는 않는다. 예를 들어 장치가 pointerdown에 persistentDeviceId가 포함될 수 있을 만큼 제때 하드웨어 ID를 디지타이저에 보고하지 않을 수 있다. 이런 경우 persistentDeviceId는 처음에는 0이었다가 유효한 값으로 변경될 수 있다.
getCoalescedEvents()

병합된 이벤트 목록을 반환하는 메서드.

getPredictedEvents()

예측된 이벤트 목록을 반환하는 메서드.

PointerEventInit 딕셔너리는 PointerEvent 인터페이스의 생성자가 신뢰할 수 없는(합성) 포인터 이벤트를 구성할 수 있는 메커니즘을 제공하는 데 사용된다. 이 딕셔너리는 MouseEventInit 딕셔너리를 상속한다. 신뢰할 수 없는 포인터 이벤트를 발생시키는 방법을 보여 주는 샘플 코드는 예제를 참조한다.

PointerEvent의 이벤트 구성 단계는 PointerEventInit의 coalescedEvents를 병합된 이벤트 목록으로 복제하고, PointerEventInit의 predictedEvents를 예측된 이벤트 목록으로 복제한다.

참고
PointerEvent 인터페이스는 MouseEvent를 상속한다. 또한 CSSOM View Module에서 제안된 확장에 유의한다. 이 확장은 분수 좌표를 허용하기 위해 여러 좌표 속성을 long에서 double로 변경한다. 이 제안된 확장을 PointerEvent에는 이미 구현했지만 일반 MouseEvent에는 구현하지 않은 사용자 에이전트에는 click, auxclick, 및 contextmenu 이벤트와 관련하여 추가 요구사항이 있다.

3.1.1 버튼 상태

3.1.1.1 동시 버튼 상호작용

마우스나 펜과 같은 일부 포인터 장치는 여러 버튼을 지원한다. Mouse Event 모델에서는 각 버튼을 누를 때마다 mousedown 및 mouseup 이벤트가 생성된다. 이러한 하드웨어 차이를 더 잘 추상화하고 장치 간 입력 작성을 단순화하기 위해 Pointer Events는 동시 버튼 누름(포인터 장치의 다른 버튼이 이미 눌린 상태에서 추가 버튼을 누르는 것)에 대해 겹치는 pointerdown 및 pointerup 이벤트를 발생시키지 않는다.

대신 동시 버튼 누름은 button 및 buttons 속성의 변화를 검사하여 감지할 수 있다. button 및 buttons 속성은 MouseEvent 인터페이스에서 상속되지만 다음 섹션에 설명된 것처럼 의미와 값이 변경된다.

button 및 buttons 속성에 대한 수정은 포인터 이벤트에만 적용된다. 그러나 click, auxclick 및 contextmenu의 경우 button 및 buttons 값은 호환성 마우스 이벤트의 경우와 마찬가지로 Mouse Event 모델을 따라야 한다 .

3.1.1.2 button 속성

모든 포인터 이벤트(pointerdown 및 pointerup뿐만 아니라)에서 버튼 상태 전환을 식별하기 위해 button 속성은 상태 변화로 이벤트를 발생시킨 장치 버튼을 나타낸다.

장치 버튼 변화 button
이전 이벤트 이후 버튼이나 터치/펜 접촉에 변화 없음 -1
왼쪽 마우스,
터치 접촉,
펜 접촉
0
가운데 마우스 1
오른쪽 마우스,
펜 배럴 버튼
2
X1(뒤로) 마우스 3
X2(앞으로) 마우스 4
펜 지우개 버튼 5
참고
마우스를 드래그하는 동안 pointermove 이벤트의 button 속성 값은 mousemove 이벤트의 값과 다르다. 예를 들어 오른쪽 버튼을 누른 상태에서 마우스를 움직이면 pointermove 이벤트의 button 값은 -1이지만 mousemove 이벤트의 button 값은 2이다.
3.1.1.3 buttons 속성

buttons 속성은 장치 버튼의 현재 상태를 비트마스크로 제공한다 (MouseEvent와 동일하지만 가능한 값의 집합이 확장됨).

장치 버튼의 현재 상태 buttons
버튼을 누르지 않은 상태에서 마우스 이동,
버튼을 누르지 않은 채 호버하면서 펜 이동
0
왼쪽 마우스,
터치 접촉,
펜 접촉
1
가운데 마우스 4
오른쪽 마우스,
펜 배럴 버튼
2
X1(뒤로) 마우스 8
X2(앞으로) 마우스 16
펜 지우개 버튼 32

3.1.2 주 포인터

다중 포인터(예: 멀티터치) 시나리오에서 isPrimary 속성은 각 포인터 유형의 활성 포인터 집합 중 주 포인터를 식별하는 데 사용된다.

  • 어느 시점에서든 각 포인터 유형에는 최대 하나의 주 포인터만 존재할 수 있다.
  • 특정 포인터 유형에서 처음 활성화되는 포인터(예: 멀티터치 상호작용에서 화면을 처음 터치하는 손가락)가 해당 포인터 유형의 주 포인터가 된다.
  • 주 포인터만 호환성 마우스 이벤트를 생성한다. 여러 주 포인터가 있는 경우 이러한 포인터는 모두 호환성 마우스 이벤트를 생성한다.
참고
단일 포인터 상호작용을 원하는 저자는 주 포인터가 아닌 포인터를 무시하여 이를 구현할 수 있다(하지만 아래의 여러 주 포인터에 대한 참고를 참조).
참고
두 개 이상의 포인터 장치 유형을 동시에 사용하는 경우 여러 포인터 (각 pointerType당 하나)가 주 포인터로 간주된다. 예를 들어 터치 접촉과 마우스 커서를 동시에 움직이면 둘 다 주 포인터로 간주되는 포인터가 생성된다.
참고
일부 장치, 운영체제 및 사용자 에이전트는 우발적인 상호작용을 방지하기 위해 둘 이상의 포인터 입력 유형을 동시에 사용하는 것을 무시할 수 있다. 예를 들어 터치와 펜 상호작용을 모두 지원하는 장치는 펜을 적극적으로 사용하는 동안 터치 입력을 무시하여 사용자가 펜을 사용하는 동안 터치스크린에 손을 올려둘 수 있게 할 수 있다(일반적으로 "팜 리젝션"이라고 하는 기능). 현재 저자가 이 동작을 억제하는 것은 불가능하다.
참고
일부 경우에는 사용자 에이전트가 어떤 포인터도 주 포인터로 표시되지 않은 포인터 이벤트를 발생시킬 수 있다. 예를 들어 멀티터치 상호작용과 같이 특정 유형의 활성 포인터가 여러 개 있는 상태에서 주 포인터가 제거되면(예: 화면을 벗어남) 주 포인터가 하나도 남지 않을 수 있다. 또한 장치의 동일한 유형의 모든 활성 포인터 (사용자 에이전트가 아닌 다른 애플리케이션을 대상으로 하는 포인터 포함)를 사용하여 주 포인터를 결정하는 플랫폼에서는 첫 번째(주) 포인터가 사용자 에이전트 밖에 있고 다른(주가 아닌) 포인터가 사용자 에이전트 안을 대상으로 하는 경우 사용자 에이전트는 다른 포인터에 대해 isPrimary 값이 false인 포인터 이벤트를 발생시킬 수 있다.
참고
현재 운영체제와 사용자 에이전트에는 일반적으로 여러 마우스 입력이라는 개념이 없다. 둘 이상의 마우스 장치가 존재하는 경우(예: 트랙패드와 외부 마우스를 모두 갖춘 노트북) 모든 마우스 장치는 일반적으로 하나의 장치로 취급된다. 어느 장치에서든 발생한 움직임은 하나의 마우스 포인터 움직임으로 변환되며, 서로 다른 마우스 장치의 버튼 누름을 구별하지 않는다. 따라서 일반적으로 마우스 포인터는 하나만 존재하며 그 포인터가 주 포인터가 된다.

3.1.3 PointerEvent 인터페이스를 사용하여 이벤트 발생시키기

e라는 이름의 포인터 이벤트를 발생시킨다는 것은 e라는 이름의 이벤트를 발생시키는 것을 의미하며, 이때 PointerEvent를 사용하고 그 속성은 PointerEvent 인터페이스 및 속성 및 기본 동작에 정의된 대로 설정한다.

이벤트가 gotpointercapture, lostpointercapture, click, auxclick 또는 contextmenu 이벤트가 아닌 경우 이 PointerEvent에 대해 대기 중인 포인터 캡처 처리 단계를 실행한다.

이벤트가 발생하는 대상을 결정하는 방법은 다음과 같다:

targetDocument를 대상의 노드 문서로 둔다 [DOM].

이벤트가 pointerdown, pointermove 또는 pointerup인 경우 이벤트의 pointerId에 대한 활성 문서를 targetDocument로 설정한다.

이벤트가 pointerdown이고, 연결된 장치가 직접 조작 장치이며 대상이 Element인 경우, 암시적 포인터 캡처에 설명된 대로 이 pointerId의 포인터 캡처를 설정하여 대상 요소를 가리키게 한다.

이 이벤트를 발생시키기 전에 사용자 에이전트는 이벤트 순서를 보장하기 위해 포인팅 장치가 previousTarget에서 대상으로 이동한 것처럼 대상을 처리하는 것이 좋다. needsOverEvent 플래그가 설정되어 있으면 대상 요소가 동일하더라도 pointerover 이벤트가 필요하다.

결정된 대상에 이벤트를 발생시킨다.

결정된 대상을 주어진 포인터의 previousTarget으로 저장하고, needsOverEvent 플래그를 false로 재설정한다. 어느 시점에서든 previousTarget이 더 이상 연결된 상태가 아니게 되면 [DOM], previousTarget에 이벤트를 디스패치하는 것에 해당하는 이벤트 경로를 따라 가장 가까운 여전히 연결된 [DOM] 부모로 previousTarget을 갱신하고 needsOverEvent 플래그를 true로 설정한다.

참고
일반적인 히트 테스트 결과 대신 포인터 캡처 대상 재정의를 대상으로 사용하면 일부 경계 이벤트가 발생할 수 있다. 이는 포인터가 이전 대상을 떠나 이 새로운 캡처 대상에 들어가는 것과 같다. 캡처가 해제될 때도 포인터가 캡처 대상을 떠나 히트 테스트 대상에 들어가기 때문에 동일한 상황이 발생할 수 있다.
3.1.3.1 속성 및 기본 동작

이 명세에서 정의된 이벤트 유형의 bubbles 및 cancelable 속성과 기본 동작은 다음 표에 나와 있다. 각 이벤트 유형에 대한 자세한 내용은 포인터 이벤트 유형에서 제공한다.

이벤트 유형 버블링 취소 가능 기본 동작
pointerover 예 예 없음
pointerenter 아니요 아니요 없음
pointerdown 예 예 상황에 따라 다름: 포인터가 주 포인터인 경우 mousedown 이벤트의 모든 기본 동작
이 이벤트를 취소하면 이후 호환성 마우스 이벤트의 발생도 방지된다.
pointermove 예 예 상황에 따라 다름: 포인터가 주 포인터인 경우 mousemove의 모든 기본 동작
pointerrawupdate 예 아니요 없음
pointerup 예 예 상황에 따라 다름: 포인터가 주 포인터인 경우 mouseup의 모든 기본 동작
pointercancel 예 아니요 없음
pointerout 예 예 없음
pointerleave 아니요 아니요 없음
gotpointercapture 예 아니요 없음
lostpointercapture 예 아니요 없음

일반적으로 직접 조작 상호작용의 결과인 뷰포트 조작 (패닝 및 확대/축소)은 의도적으로 포인터 이벤트의 기본 동작이 아니다. 이는 이러한 동작 (예: 터치스크린에서 손가락을 움직여 페이지를 패닝하는 동작)을 포인터 이벤트를 취소하여 억제할 수 없음을 의미한다. 저자는 대신 touch-action을 사용하여 문서의 특정 영역에 대한 직접 조작 동작을 선언해야 한다. 이벤트 취소에 대한 이러한 의존성을 제거하면 사용자 에이전트가 성능을 최적화하기 쉬워진다.

pointerenter 및 pointerleave 이벤트의 경우 composed [DOM] 속성은 false인 것이 좋고, 위 표의 다른 모든 포인터 이벤트에 대해서는 이 속성이 true인 것이 좋다.

위 표의 모든 포인터 이벤트에 대해 detail 속성은 0인 것이 좋다.

참고
많은 사용자 에이전트는 레거시 콘텐츠를 지원하기 위해 MouseEvents에 비표준 속성 fromElement 및 toElement를 노출한다. 저자가 표준화된 대안(target 및 relatedTarget)을 사용하도록 전환하기 위해 이러한 사용자 에이전트가 PointerEvents에서 해당 (상속된) 속성의 값을 null로 설정할 것을 권장한다.

MouseEvent relatedTarget과 유사하게, relatedTarget은 포인터가 방금 경계를 벗어난 요소(pointerover 또는 pointerenter 이벤트의 경우) 또는 포인터가 경계 안으로 들어가는 요소 (pointerout 또는 pointerleave 이벤트의 경우)로 초기화해야 한다. 다른 포인터 이벤트에서는 이 값의 기본값이 null이다. 요소가 포인터 캡처를 받으면 해당 포인터의 이후 모든 이벤트가 캡처 요소의 경계 내부에 있는 것으로 간주됨에 유의한다.

gotpointercapture 및 lostpointercapture 이벤트의 경우, 위 표에서 정의된 속성을 제외한 모든 속성은 사용자 에이전트가 대기 중인 포인터 캡처 처리 단계를 실행하고 gotpointercapture 및 lostpointercapture 이벤트를 발생시키게 한 Pointer Event와 동일해야 한다.

3.1.3.2 대기 중인 포인터 캡처 처리

사용자 에이전트는 포인터 캡처를 암시적으로 해제할 때뿐만 아니라 gotpointercapture 또는 lostpointercapture가 아닌 Pointer Events를 발생시킬 때도 다음 단계를 실행해야 한다.

  1. 이 포인터의 포인터 캡처 대상 재정의가 설정되어 있고 대기 중인 포인터 캡처 대상 재정의와 같지 않은 경우 lostpointercapture라는 이름의 포인터 이벤트를 포인터 캡처 대상 재정의 노드에서 발생시킨다.
  2. 이 포인터의 대기 중인 포인터 캡처 대상 재정의가 설정되어 있고 포인터 캡처 대상 재정의와 같지 않은 경우, gotpointercapture라는 이름의 포인터 이벤트를 대기 중인 포인터 캡처 대상 재정의에서 발생시킨다.
  3. 포인터 캡처 대상 재정의를 대기 중인 포인터 캡처 대상 재정의가 설정되어 있으면 그 값으로 설정한다. 그렇지 않으면 포인터 캡처 대상 재정의를 지운다.
참고

click, auxclick 및 contextmenu 이벤트에 대한 섹션에 정의된 대로, lostpointercapture 이벤트가 이미 디스패치된 후에도 해당 click, auxclick 또는 contextmenu 이벤트가 있다면 여전히 캡처 대상으로 디스패치된다.

3.1.3.3 포인터 이벤트 스트림 억제

사용자 에이전트는 웹 페이지가 특정 pointerId를 가진 포인터 이벤트를 계속 수신할 가능성이 낮다고 감지하면 포인터 이벤트 스트림을 억제해야 한다. 다음 시나리오 중 하나라도 이 조건을 충족한다 (추가 시나리오가 있을 수 있다):

  • 사용자 에이전트가 모달 대화상자 또는 메뉴를 열었다.
  • 포인터 입력 장치가 물리적으로 연결 해제되었거나, 호버 가능한 포인터 입력 장치 (예: 호버 가능한 펜/스타일러스)가 디지타이저가 감지할 수 있는 호버 범위를 벗어났다.
  • 이후 사용자 에이전트가 포인터를 사용하여 페이지 뷰포트를 조작한다 (예: 패닝 또는 확대/축소). 자세한 내용은 touch-action CSS 속성에 대한 섹션을 참조한다.
    참고
    사용자 에이전트는 여러 포인터 유형(예: 터치 및 펜)을 통해 패닝 또는 확대/축소를 트리거할 수 있으므로, 패닝 또는 확대/축소 동작의 시작으로 인해 서로 다른 포인터 유형의 포인터를 포함한 다양한 포인터가 억제될 수 있다.
  • 드래그 앤 드롭 처리 모델 [HTML]에 정의된 드래그 작업 시작 알고리즘의 일부로, 드래그 작업을 발생시킨 포인터에 대해.
참고

사용자 에이전트가 포인터 이벤트 스트림을 억제할 수 있는 다른 시나리오는 다음과 같다:

  • 포인터가 활성 상태인 동안 장치의 화면 방향이 변경된다.
  • 사용자가 장치가 지원하는 것보다 더 많은 포인터 입력을 동시에 사용하여 상호작용하려 한다.
  • 사용자 에이전트가 입력을 우발적인 것으로 해석한다(예: 하드웨어가 팜 리젝션을 지원함).

이러한 시나리오를 감지하는 방법은 이 명세의 범위를 벗어난다.

사용자 에이전트는 포인터 이벤트 스트림을 억제하기 위해 다음 단계를 실행해야 한다:

3.1.4 레이아웃 변경으로 인한 경계 이벤트

화면 표면을 기준으로 이동했거나 속성 중 하나라도 변화한 포인팅 장치는 포인터 이벤트 유형에 정의된 여러 이벤트를 발생시킨다. 정지한 포인팅 장치(화면 표면을 기준으로 이동하지도 않았고 어떤 속성도 변화하지 않은 장치)의 경우 사용자 에이전트는 포인터의 히트 테스트 대상에 영향을 준 레이아웃 변경 후 특정 경계 이벤트를 발생시켜야 한다. 자세한 내용은 pointerover, pointerenter, pointerout 및 pointerleave를 참조한다. 사용자 에이전트는 성능상의 이유(예: 지나치게 많은 히트 테스트 또는 경계 이벤트 리스너로 인한 레이아웃 변경을 방지하기 위해) 이러한 경계 이벤트의 발생을 지연할 수 있다.

참고
정지한 포인팅 장치(화면 표면을 기준으로 이동하지도 않았고 어떤 속성도 변화하지 않은 장치)는 pointermove 이벤트를 발생시키지 않는다.

3.1.5 tiltX / tiltY와 altitudeAngle / azimuthAngle 간 변환

Pointer Events에는 X-Y 평면을 기준으로 트랜스듀서의 방향을 표현하기 위한 상호 보완적인 두 속성 집합, 즉 tiltX / tiltY(원래 Pointer Events 명세에 도입됨)와 azimuthAngle / altitudeAngle(Touch Events - Level 2 명세에서 채택됨)이 포함된다.

특정 하드웨어 및 플랫폼에 따라 사용자 에이전트는 화면 평면을 기준으로 한 트랜스듀서 방향에 대해 tiltX / tiltY 또는 altitudeAngle / azimuthAngle 중 하나의 값 집합만 받을 가능성이 높다. 사용자 에이전트는 이러한 값을 변환할 때 다음 알고리즘을 사용해야 한다.

사용자 에이전트가 azimuthAngle / altitudeAngle에서 tiltX / tiltY를 계산할 때 최종 정수 값은 Math.round [ECMASCRIPT] 규칙을 사용하여 반올림하는 것이 좋다.

예제 1: tiltX/tiltY와 altitudeAngle/azimuthAngle 간 변환
/* tiltX/tiltY와 altitudeAngle/azimuthAngle 간 변환 */

function spherical2tilt(altitudeAngle, azimuthAngle) {
  const radToDeg = 180/Math.PI;

  let tiltXrad = 0;
  let tiltYrad = 0;

  if (altitudeAngle == 0) {
    // 펜이 X-Y 평면에 있다
    if (azimuthAngle == 0 || azimuthAngle == 2*Math.PI) {
      // 펜이 양의 X축에 있다
      tiltXrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI/2) {
      // 펜이 양의 Y축에 있다
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle == Math.PI) {
      // 펜이 음의 X축에 있다
      tiltXrad = -Math.PI/2;
    }
    if (azimuthAngle == 3*Math.PI/2) {
      // 펜이 음의 Y축에 있다
      tiltYrad = -Math.PI/2;
    }
    if (azimuthAngle>0 && azimuthAngle<Math.PI/2) {
      tiltXrad = Math.PI/2;
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle>Math.PI/2 && azimuthAngle<Math.PI) {
      tiltXrad = -Math.PI/2;
      tiltYrad = Math.PI/2;
    }
    if (azimuthAngle>Math.PI && azimuthAngle<3*Math.PI/2) {
      tiltXrad = -Math.PI/2;
      tiltYrad = -Math.PI/2;
    }
    if (azimuthAngle>3*Math.PI/2 && azimuthAngle<2*Math.PI) {
      tiltXrad = Math.PI/2;
      tiltYrad = -Math.PI/2;
    }
  }

  if (altitudeAngle != 0) {
    const tanAlt = Math.tan(altitudeAngle);

    tiltXrad = Math.atan(Math.cos(azimuthAngle) / tanAlt);
    tiltYrad = Math.atan(Math.sin(azimuthAngle) / tanAlt);
  }

  return {"tiltX":tiltXrad*radToDeg, "tiltY":tiltYrad*radToDeg};
}

function tilt2spherical(tiltX, tiltY) {
  const tiltXrad = tiltX * Math.PI/180;
  const tiltYrad = tiltY * Math.PI/180;

  // 방위각 계산
  let azimuthAngle = 0;

  if (tiltX == 0) {
    if (tiltY > 0) {
      azimuthAngle = Math.PI/2;
    }
    else if (tiltY < 0) {
      azimuthAngle = 3*Math.PI/2;
    }
  } else if (tiltY == 0) {
    if (tiltX < 0) {
      azimuthAngle = Math.PI;
    }
  } else if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
    // 방위각을 계산하기에 정보가 충분하지 않음
    azimuthAngle = 0;
  } else {
    // 경계가 아닌 경우: tiltX와 tiltY 모두 0 또는 +-90이 아님
    const tanX = Math.tan(tiltXrad);
    const tanY = Math.tan(tiltYrad);

    azimuthAngle = Math.atan2(tanY, tanX);
    if (azimuthAngle < 0) {
      azimuthAngle += 2*Math.PI;
    }
  }

  // 고도각 계산
  let altitudeAngle = 0;

  if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) {
      altitudeAngle = 0
  } else if (tiltX == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltYrad);
  } else if (tiltY == 0) {
    altitudeAngle = Math.PI/2 - Math.abs(tiltXrad);
  } else {
    // 경계가 아닌 경우: tiltX와 tiltY 모두 0 또는 +-90이 아님
    altitudeAngle =  Math.atan(1.0/Math.sqrt(Math.pow(Math.tan(tiltXrad),2) + Math.pow(Math.tan(tiltYrad),2)));
  }

  return {"altitudeAngle":altitudeAngle, "azimuthAngle":azimuthAngle};
}

3.2 PointerEvent 알고리즘

3.2.1 PointerEvent 초기화

event, eventType 및 eventTarget, bubbles, 그리고 cancelable로 PointerEvent를 초기화하려면 다음 단계를 실행한다:

  1. event, eventType 및 eventTarget, bubbles 및 cancelable로 MouseEvent를 초기화한다
  2. 다른 모든 속성을 기본 PointerEvent 값으로 초기화한다.

3.2.2 PointerEvent 생성

eventType 및 eventTarget, bubbles, 그리고 cancelable로 PointerEvent를 생성하려면 다음 단계를 실행한다:

  1. event를 PointerEvent를 사용하여 이벤트를 생성한 결과로 둔다
  2. event, eventType 및 eventTarget, bubbles 및 cancelable로 PointerEvent를 초기화한다
  3. event를 반환한다

3.2.3 MouseEvent에서 PointerEvent 생성

  1. eventType을 이벤트 유형을 포함하는 DOMString으로 둔다
  2. mouseevent를 해당 MouseEvent로 둔다
  3. event를 PointerEvent를 사용하여 이벤트를 생성한 결과로 둔다
  4. target을 mouseevent.target으로 둔다
  5. event, eventType 및 target으로 PointerEvent를 초기화한다
  6. MouseEvent 속성을 mouseevent에서 event로 복사한다
  7. event를 반환한다

3.3 포인터 이벤트 유형

다음은 이 명세에서 정의하는 이벤트 유형이다.

주 포인터의 경우 이러한 이벤트(gotpointercapture 및 lostpointercapture 제외)는 호환성 마우스 이벤트도 발생시킬 수 있다.

3.3.1 pointerover

유형 pointerover
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerover라고 명명해야 한다:

3.3.2 pointerenter

유형 pointerenter
인터페이스 PointerEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 반드시 포인터 이벤트를 발생시켜야 합니다. 이벤트 이름은 pointerenter이며, 다음 중 하나가 발생하면 발생시킵니다:

  • 해당 단계인 대상 결정에서 포인터에 대해 감지한 사실이 포인터가 요소 또는 그 자손 중 하나로 이동했다는 것인 경우입니다.
  • 레이아웃 변경으로 인해 히트 테스트에서 사용하는 요소 또는 그 자손 중 하나의 경계가 정지된 포인팅 장치의 캡처되지 않은 포인터 아래로 이동하는 경우입니다.
  • 사용자 에이전트가 발생시키기 전인 pointerdown 이벤트의 대상 장치가 호버를 지원하지 않는 경우입니다 (참조: pointerdown).
참고
이 이벤트 유형은 다음과 유사합니다: pointerover. 하지만 두 가지 차이가 있습니다: pointerenter는 버블링되지 않으며, 이 이벤트의 디스패치는 고려 대상인 히트 테스트 경계에 자손 요소의 경계까지 포함합니다.
참고
이 이벤트 유형은 mouseenter 이벤트와 유사하며 , 또한 다음에 설명된 CSS :hover 의사 클래스와도 유사합니다 [CSS21]. 다음도 참조하세요: pointerleave 이벤트.

3.3.3 pointerdown

유형 pointerdown
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 반드시 포인터 이벤트를 발생시켜야 합니다. 이벤트 이름은 pointerdown이며, 포인터가 다음 상태에 들어갈 때 발생시킵니다: 활성 버튼 상태. 마우스의 경우, 이는 장치가 어느 버튼도 눌리지 않은 상태에서 하나 이상의 버튼이 눌린 상태로 전환할 때입니다. 터치의 경우, 이는 물리적인 접촉이 이루어질 때이며, 접촉 대상은 디지타이저입니다. 펜의 경우, 이는 펜이 어떤 버튼도 눌리지 않은 채 디지타이저와 물리적으로 접촉하거나, 상태가 전환되어 호버링 중에 어느 버튼도 눌리지 않은 상태에서 하나 이상의 버튼이 눌린 상태가 될 때입니다.

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdown과 pointerup이 동일한 모든 경우에 발생하지는 않는다는 뜻이며, 그 상황은 mousedown과 mouseup의 발생 상황입니다. 다음을 참조하세요: 버튼 동시 누름에 자세한 정보가 있습니다.

입력 장치가 지원하지 않는 것이 호버인 경우, 사용자 에이전트가 반드시 추가로 발생시켜야 하는 포인터 이벤트의 이름은 pointerover이며, 그 뒤에 이어지는 포인터 이벤트의 이름은 pointerenter입니다. 이는 다음보다 앞서야 합니다: 디스패치되는 pointerdown 이벤트.

참고
작성자는 발생을 방지할 수 있으며, 그 대상은 특정 호환성 마우스 이벤트입니다. 이를 위해 취소하는 대상은 pointerdown 이벤트입니다(다음 조건을 만족하는 경우: isPrimary 속성이 true). 이렇게 하면 PREVENT MOUSE EVENT 플래그가 포인터에 설정됩니다. 다만 다음을 방지하지는 않는다는 점에 유의하세요: mouseover, mouseenter, mouseout 또는 mouseleave 이벤트의 발생.

3.3.4 pointermove

유형 pointermove
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

포인터에서 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성이 변경되면 사용자 에이전트는 포인터 이벤트를 발생시켜 pointermove라고 명명해야 한다. 여기에는 좌표, 압력, 접선 압력, 기울기, 비틀림, 접촉 형상(width 및 height) 또는 동시 버튼의 변경이 포함된다.

사용자 에이전트는 pointermove 이벤트의 디스패치를 (예: 성능상의 이유로) 지연할 수 있다. 병합된 이벤트 정보는 디스패치된 단일 pointermove 이벤트에 대해 getCoalescedEvents 메서드를 통해 노출된다. 이러한 이벤트의 최종 좌표를 이벤트의 대상을 찾는 데 사용해야 한다.

3.3.5 pointerrawupdate

유형 pointerrawupdate
인터페이스 PointerEvent
버블링 예
취소 가능 아니요
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

포인터에서 pointerdown 또는 pointerup 이벤트를 발생시키지 않는 속성이 변경되면 사용자 에이전트는 포인터 이벤트를 발생시켜 pointerrawupdate라고 명명해야 하며, 보안 컨텍스트 내에서만 그렇게 해야 한다. 이러한 속성의 목록은 pointermove 이벤트를 참조한다.

pointermove와 달리, 사용자 에이전트는 pointerrawupdate 이벤트를 가능한 한 빨리, JavaScript가 이벤트를 처리할 수 있는 만큼 자주 디스패치하는 것이 좋다.

pointerrawupdate 이벤트의 target은 pointermove 이벤트와 다를 수 있다. 이는 pointermove 이벤트가 지연되거나 병합될 수 있고, target을 찾는 데 사용되는 이벤트의 최종 위치가 병합된 이벤트와 다를 수 있기 때문이다.

아직 이벤트 루프에서 디스패치되지 않은 동일한 pointerId를 가진 다른 pointerrawupdate가 이미 있는 경우, 사용자 에이전트는 새 pointerrawupdate를 새 태스크를 생성하는 대신 해당 이벤트와 병합할 수 있다. 이로 인해 pointerrawupdate에 병합된 이벤트가 포함될 수 있으며, 이벤트가 이벤트 루프에서 처리되는 즉시 모두 하나의 pointerrawupdate 이벤트의 병합된 이벤트로 전달된다. 자세한 내용은 getCoalescedEvents를 참조한다.

pointerrawupdate와 pointermove의 순서와 관련하여, 사용자 에이전트가 플랫폼으로부터 pointerrawupdate 및 pointermove 이벤트를 모두 발생시키는 업데이트를 수신한 경우, 사용자 에이전트는 해당 pointermove보다 먼저 pointerrawupdate 이벤트를 디스패치해야 한다.

target을 제외하면 마지막 pointermove 이벤트 이후 디스패치된 모든 pointerrawupdate 이벤트의 병합된 이벤트 목록을 연결한 것은 다른 이벤트 속성 측면에서 다음 pointermove 이벤트의 병합된 이벤트와 동일하다. pointerrawupdate의 속성은 대부분 pointermove와 동일하지만, pointerrawupdate에서는 cancelable이 반드시 false여야 한다는 점이 다르다.

사용자 에이전트는 pointerrawupdate에 대해 호환성 마우스 이벤트를 발생시키지 않는 것이 좋다.

참고
pointerrawupdate 이벤트에 리스너를 추가하면 사용자 에이전트의 구현에 따라 웹 페이지 성능에 부정적인 영향을 줄 수 있다. 대부분의 사용 사례에서는 다른 pointerevent 유형으로 충분하다. JavaScript가 고주파 이벤트를 필요로 하고 이를 그만큼 빠르게 처리할 수 있는 경우에만 pointerrawupdate 리스너를 추가해야 한다. 이러한 경우 다른 유형의 포인터 이벤트를 수신할 필요는 없을 가능성이 높다.

3.3.6 pointerup

유형 pointerup
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 반드시 포인터 이벤트를 발생시켜야 합니다. 이벤트 이름은 pointerup이며, 포인터가 다음 상태에서 벗어날 때 발생시킵니다: 활성 버튼 상태. 마우스의 경우, 이는 장치가 하나 이상의 버튼이 눌린 상태에서 어느 버튼도 눌리지 않은 상태로 전환할 때입니다. 터치의 경우, 이는 물리적인 접촉이 해제될 때이며, 접촉 대상은 디지타이저입니다. 펜의 경우, 이는 펜이 어떤 버튼도 눌리지 않은 상태에서 디지타이저와의 물리적인 접촉이 해제되거나, 상태가 전환되어 호버링 중에 하나 이상의 버튼이 눌린 상태에서 어느 버튼도 눌리지 않은 상태가 될 때입니다.

입력 장치가 지원하지 않는 것이 호버인 경우, 사용자 에이전트가 반드시 추가로 발생시켜야 하는 포인터 이벤트의 이름은 pointerout이며, 그 뒤에 이어지는 포인터 이벤트의 이름은 pointerleave입니다. 이 이벤트들은 다음 이후에 발생해야 합니다: 디스패치되는 pointerup 이벤트.

모든 pointerup 이벤트의 pressure 값은 0입니다.

사용자 에이전트가 반드시 추가로 암묵적으로 해제해야 하는 것은 포인터 캡처이며, 포인터가 현재 캡처된 경우에 적용됩니다.

참고
마우스(또는 다른 다중 버튼 포인터 장치)의 경우, 이는 pointerdown과 pointerup이 동일한 모든 경우에 발생하지는 않는다는 뜻이며, 그 상황은 mousedown과 mouseup의 발생 상황입니다. 다음을 참조하세요: 버튼 동시 누름에 자세한 정보가 있습니다.

3.3.7 pointercancel

유형 pointercancel
인터페이스 PointerEvent
버블링 예
취소 가능 아니요
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인터 이벤트 스트림을 억제해야 하는 시나리오를 감지하면 포인터 이벤트를 발생시켜 pointercancel이라고 명명해야 한다.

pointercancel 이벤트의 다음 속성 값은 동일한 pointerId를 가진 마지막으로 디스패치된 포인터 이벤트의 값과 일치해야 한다: width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle, pointerType, isPrimary, 그리고 Mouse Events에서 상속된 좌표. pointercancel 이벤트의 coalescedEvents 및 predictedEvents 목록은 비어 있어야 하며, 이벤트의 cancelable 속성은 반드시 false여야 한다.

3.3.8 pointerout

유형 pointerout
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 다음 중 하나가 발생하면 포인터 이벤트를 발생시켜 pointerout이라고 명명해야 한다:

3.3.9 pointerleave

유형 pointerleave
인터페이스 PointerEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 반드시 포인터 이벤트를 발생시켜야 합니다. 이벤트 이름은 pointerleave이며, 다음 중 하나가 발생하면 발생시킵니다:

  • 해당 단계인 대상 결정에서 포인터에 대해 감지한 사실이 포인터가 요소 및 그 모든 자손의 바깥으로 이동했다는 것인 경우입니다.
  • 레이아웃 변경으로 인해 히트 테스트에서 사용하는 요소 및 그 모든 자손의 경계가 정지된 포인팅 장치의 캡처되지 않은 포인터 아래에서 벗어나 이동하는 경우입니다.
  • 사용자 에이전트가 발생시킨 후로, pointerup 이벤트가 발생한 입력 장치가 호버를 지원하지 않는 경우입니다 (참조: pointerup).
  • 사용자 에이전트가 다음을 수행할 상황을 감지한 경우입니다: 포인터 이벤트 스트림 억제.
참고
이 이벤트 유형은 다음과 유사합니다: pointerout. 하지만 두 가지 차이가 있습니다: pointerleave는 버블링되지 않으며, 이 이벤트의 디스패치는 고려 대상인 히트 테스트 경계에 자손 요소의 경계까지 포함합니다.
참고
이 이벤트 유형은 mouseleave 이벤트와 유사하며, 다음에 설명된 CSS :hover 의사 클래스와도 유사합니다 [CSS21]. 다음도 참조하세요: pointerenter 이벤트.

3.3.10 gotpointercapture

유형 gotpointercapture
인터페이스 PointerEvent
버블링 예
취소 가능 아니요
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

요소가 포인터 캡처를 받으면 사용자 에이전트는 포인터 이벤트를 발생시켜 gotpointercapture라고 명명해야 한다. 이 이벤트는 포인터 캡처를 받는 요소에서 발생한다. 이후 해당 포인터의 이벤트는 이 요소에서 발생한다. 포인터 캡처 설정 및 대기 중인 포인터 캡처 처리 섹션을 참조한다.

3.3.11 lostpointercapture

유형 lostpointercapture
인터페이스 PointerEvent
버블링 예
취소 가능 아니요
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

포인터의 포인터 캡처가 해제된 후 사용자 에이전트는 포인터 이벤트를 발생시켜 lostpointercapture라고 명명해야 한다. 이 이벤트는 캡처가 해제된 후 해당 포인터의 후속 이벤트보다 먼저 발생해야 한다. 이 이벤트는 포인터 캡처가 제거된 요소에서 발생한다. click, auxclick 및 contextmenu 이벤트를 제외한 해당 포인터의 모든 후속 이벤트는 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따른다. 포인터 캡처 해제, 포인터 캡처의 암시적 해제 및 대기 중인 포인터 캡처 처리 섹션을 참조한다.

3.3.12 click, auxclick 및 contextmenu

이 섹션은 MouseEvent의 click, auxclick 및 contextmenu 이벤트 정의에 추가되는 내용이다. 이러한 이벤트는 일반적으로 사용자 인터페이스 활성화와 연관되며 키보드와 같은 비포인터 입력 장치에서도 발생한다.

이러한 이벤트는 PointerEvent 유형이어야 하며, 이 섹션의 나머지 부분에 언급된 추가 요구사항의 적용을 받는다.

3.3.12.1 이벤트 속성

이러한 이벤트의 경우 pointerId 및 pointerType을 제외한 모든 PointerEvent 전용 속성 (이 명세에서 정의됨)은 기본값을 가져야 한다. 또한:

  • 이벤트가 포인팅 장치에서 생성된 경우 해당 pointerId 및 pointerType은 이러한 이벤트를 발생시킨 PointerEvents와 동일해야 한다.
  • 이벤트가 비포인팅 장치(예: 음성 인식 소프트웨어 또는 키보드 상호작용)에서 생성된 경우 pointerId는 -1이어야 하고, pointerType은 빈 문자열이어야 한다.
3.3.12.2 이벤트 좌표

PointerEvent에서 언급했듯이 CSSOM View Module은 분수 좌표를 허용하기 위해 여러 좌표 속성 (screenX, screenY, pageX, pageY, clientX, clientY, x, y, offsetX, offsetY)을 double로 재정의할 것을 제안한다. 그러나 이 변경이 일반 MouseEvent에는 적용되지 않고 PointerEvent에만 적용되는 경우 click, auxclick 및 contextmenu에서 레거시 코드와의 웹 호환성 문제가 발생하는 것으로 확인되었다. 따라서 CSSOM View Module에서 제안된 변경을 PointerEvent에만 구현한 사용자 에이전트는 click, auxclick 및 contextmenu의 여러 좌표 속성을 Math.floor [ECMASCRIPT]를 사용하여 long 값(원래 Mouse Events에 정의된 값)으로 변환해야 한다.

3.3.12.3 이벤트 디스패치

click, auxclick 또는 contextmenu 이벤트는 반드시 표준 디스패치 절차를 따라야 하지만, 이벤트 대상은 예외적으로 아래 알고리즘을 사용하여 재정의됩니다:

  1. event는 click, auxclick 또는 contextmenu 이벤트 중 디스패치 중인 이벤트로 두고, userEvent는 사용자 상호작용 이벤트로서 event의 발생을 유발한 이벤트로 둡니다.

    참고

    이벤트 userEvent는 PointerEvent가 아닐 수도 있습니다. 예를 들어, 이 이벤트는 KeyboardEvent입니다. 이는 click 이벤트의 디스패치가 체크박스 요소에서 스페이스바를 눌러 발생한 경우입니다.

    userEvent가 PointerEvent인 경우, userEvent는 pointerup이며, 이는 click 또는 auxclick 이벤트의 경우이고, pointerdown 또는 pointerup 이벤트(네이티브 플랫폼의 관례에 따라 결정됨)는 contextmenu 이벤트의 경우에 해당합니다.

  2. userEvent가 PointerEvent가 아니면 event를 디스패치하되, event의 대상을 재정의하지 않고 아래의 나머지 단계를 건너뜁니다.
  3. target을 다음과 같이 정의합니다:

    event가 contextmenu 이벤트이거나, userEvent가 해당 포인터가 캡처된 동안 디스패치되었다면, target은 userEvent의 대상으로 둡니다.

    그렇지 않으면(event가 click 또는 auxclick 이벤트이며, 이에 대한 userEvent는 pointerup 이벤트로서 디스패치될 때 캡처되지 않은 경우), target을 가장 가까운 공통 포괄적 조상으로 두며, 이는 해당 pointerdown 및 pointerup 대상들의 DOM 내 조상으로서, event가 디스패치되는 시점을 기준으로 합니다.

  4. event를 target에 디스패치합니다.

    참고
    userEvent가 캡처되었다면 event가 디스패치되는 대상은 userEvent의 캡처 대상이며, 다음의 경우에도 그렇습니다: lostpointercapture 이벤트가 동일한 pointerId로 이미 디스패치된 경우입니다.

4. Element 인터페이스 확장

다음 섹션에서는 포인터 캡처의 설정 및 해제를 용이하게 하기 위한 기존 Element 인터페이스의 확장을 설명한다.

WebIDLpartial interface Element {
  undefined setPointerCapture (long pointerId);
  undefined releasePointerCapture (long pointerId);
  boolean hasPointerCapture (long pointerId);
};
setPointerCapture()

인수 pointerId로 식별되는 포인터의 포인터 캡처를 설정하여 이 메서드가 호출된 요소를 가리키게 한다. 포인터의 후속 이벤트에서는 포인터가 항상 캡처 대상 위에 있는 것처럼 캡처 대상이 일반적인 히트 테스트 결과를 대신하며, 캡처가 해제될 때까지 이러한 이벤트는 항상 이 요소를 대상으로 해야 한다. 이 메서드가 효과를 가지려면 포인터가 활성 버튼 상태에 있어야 하며, 그렇지 않으면 아무 알림 없이 실패한다. 제공된 메서드의 인수가 활성 포인터 중 어느 것과도 일치하지 않으면 "NotFoundError" DOMException을 발생시킨다.

releasePointerCapture()

인수 pointerId로 식별되는 포인터의 포인터 캡처를 해제하여 이 메서드가 호출된 요소에서 제거한다. 포인터의 후속 이벤트는 이벤트 대상을 결정하기 위해 일반적인 히트 테스트 메커니즘(이 명세의 범위를 벗어남)을 따른다. 제공된 메서드의 인수가 활성 포인터 중 어느 것과도 일치하지 않으면 "NotFoundError" DOMException을 발생시킨다.

hasPointerCapture

이 메서드가 호출된 요소가 인수 pointerId로 식별되는 포인터에 대해 포인터 캡처를 보유하고 있는지 나타낸다. 특히 대기 중인 포인터 캡처 대상 재정의가 pointerId에 대해 이 메서드가 호출된 요소로 설정되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환한다.

참고
이 메서드는 호출 직후 true를 반환하며, 호출 대상은 setPointerCapture()입니다. 이는 해당 요소가 아직 받지 않았더라도 마찬가지이며, 그 대상은 gotpointercapture 이벤트입니다. 그 결과, 다음을 감지하는 데 유용할 수 있습니다: 암묵적 포인터 캡처. 이를 감지하는 위치는 pointerdown 이벤트 리스너 내부입니다.

5. GlobalEventHandlers 믹스인 확장

다음 섹션에서는 이벤트 핸들러 등록을 용이하게 하기 위한 기존 GlobalEventHandlers 믹스인의 확장을 설명한다.

WebIDLpartial interface mixin GlobalEventHandlers {
    attribute EventHandler onpointerover;
    attribute EventHandler onpointerenter;
    attribute EventHandler onpointerdown;
    attribute EventHandler onpointermove;
    [SecureContext] attribute EventHandler onpointerrawupdate;
    attribute EventHandler onpointerup;
    attribute EventHandler onpointercancel;
    attribute EventHandler onpointerout;
    attribute EventHandler onpointerleave;
    attribute EventHandler ongotpointercapture;
    attribute EventHandler onlostpointercapture;
};
onpointerover
pointerover 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerenter
pointerenter 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerdown
pointerdown 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointermove
pointermove 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerrawupdate
pointerrawupdate 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerup
pointerup 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointercancel
pointercancel 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerout
pointerout 이벤트 유형의 이벤트 핸들러 IDL 속성.
onpointerleave
pointerleave 이벤트 유형의 이벤트 핸들러 IDL 속성.
ongotpointercapture
gotpointercapture 이벤트 유형의 이벤트 핸들러 IDL 속성.
onlostpointercapture
lostpointercapture 이벤트 유형의 이벤트 핸들러 IDL 속성.

6. Navigator 인터페이스 확장

Navigator 인터페이스는 [HTML]에 정의되어 있다. 이 명세는 장치 감지 지원을 제공하기 위해 Navigator 인터페이스를 확장한다.

WebIDLpartial interface Navigator {
    readonly  attribute long maxTouchPoints;
};
maxTouchPoints

getter 단계는 다음과 같다:

  1. emulated maxTouchPoints를 WebDriver BiDi 에뮬레이션된 최대 터치 포인트 [WEBDRIVER-BIDI]의 결과로 둔다.
  2. emulated maxTouchPoints가 null이 아니면 emulated maxTouchPoints를 반환한다.
  3. 장치가 지원하는 최대 동시 터치 접촉 수를 반환한다. 여러 디지타이저가 있는 장치(예: 여러 터치스크린)의 경우 이 값은 각 개별 디지타이저가 지원하는 최대 접촉 수 집합의 최댓값이어야 한다.

    예를 들어 장치에 각각 2개, 5개, 10개의 동시 터치 접촉을 지원하는 터치스크린 3개가 있다고 가정한다. maxTouchPoints 값은 10이어야 한다.

참고
maxTouchPoints 값이 0보다 크다는 것은 사용자의 장치가 터치 입력을 지원할 수 있음을 나타내지만, 이것이 반드시 사용자가 실제로 터치 입력을 사용한다는 뜻은 아닙니다. 작성자는 다른 입력 방식도 주의 깊게 고려해야 하며, 시스템에 존재할 수 있는 방식으로는 마우스, 펜 또는 스크린 리더 등이 있습니다.
참고
maxTouchPoints는 상호작용 모델의 인식 가능 여부를 확인하는 데 자주 사용되며, 콘텐츠의 모델이 현재 하드웨어에서 인식될 수 있는지 확인합니다. UI 어포던스를 사용자에게 제공할 수 있으며, 이는 기능이 더 제한된 하드웨어의 경우입니다. 정확한 터치 지점 수를 알 수 없는 플랫폼에서는, 최소 인식 보장 개수가 제공됩니다. 따라서 다음과 같은 개수 관계가 성립할 수 있습니다: 인식되는 터치 지점 수가 maxTouchPoints 값을 초과합니다.

7. 직접 조작 동작 선언

속성 및 기본 동작에서 언급했듯이 뷰포트 조작(패닝 및 확대/축소)은 포인터 이벤트를 취소하여 억제할 수 없다. 대신 저자는 touch-action CSS 속성을 사용하여 이러한 동작 중 어떤 것을 허용하고 어떤 것을 억제할지 선언적으로 정의해야 한다.

참고
뷰포트를 조작하는 데 사용되는 포인터 문제는 일반적으로 터치 입력 (사용자의 손가락으로 콘텐츠와 상호작용하면서 페이지를 패닝/확대/축소할 수 있는 경우)에 한정되지만, 일부 사용자 에이전트는 다른 포인터 유형에도 동일한 종류의 (직접 또는 간접) 조작을 허용할 수 있다. 예를 들어 모바일/태블릿 장치에서는 스타일러스를 사용하여 스크롤할 수도 있다. 역사적인 이유로 이 명세에서 정의하는 touch-action CSS 속성은 터치 입력만을 가리키는 것처럼 보이지만, 실제로는 패닝 및 확대/축소를 위한 직접 조작을 허용하는 모든 형태의 포인터 입력에 적용된다.

7.1 touch-action CSS 속성

이름: touch-action
값: auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
초깃값: auto
적용 대상: 대체되지 않은 인라인 요소, 테이블 행, 행 그룹, 테이블 열, 열 그룹을 제외한 모든 요소
상속: 아니요
백분율: 해당 없음
미디어: 시각적
계산값: 지정된 값과 동일
정규 순서: 문법에 따름
애니메이션 유형: 애니메이션 불가

touch-action CSS 속성은 직접 조작 상호작용(속성 이름과 달리 터치에만 한정되지 않음)이 사용자 에이전트의 패닝 및 확대/축소 동작을 트리거할 수 있는지 결정한다. touch-action 값에 대한 섹션을 참조한다.

패닝 또는 확대/축소를 시작하기 직전에 다음 조건이 모두 참이면 사용자 에이전트는 포인터 이벤트 스트림을 억제해야 한다:

참고
일부 사용자 에이전트는 일련의 제스처를 수반하는 동작을 위해 복합 제스처를 구현하며, 이들은 서로 분리된 개별 제스처이지만 모두 하나의 연속된 제스처의 일부로 취급됩니다. 예를 들어, 터치스크린에서의 "플링으로 스크롤" 제스처를 생각해 보세요: 사용자가 문서의 패닝을 시작하는데, 빠른 손가락 움직임으로 시작한 뒤 터치스크린에서 손가락을 떼어도 문서는 계속해서 시뮬레이션된 관성으로 패닝됩니다. 문서가 계속 움직이는 동안, 사용자는 손가락을 놓을 수 있으며, 터치스크린에 놓고 또 다른 "플링"을 수행하여 패닝에 추가적인 운동량을 제공하거나, 현재 패닝에 반대되는 동작으로 속도를 늦추거나, 패닝을 완전히 멈추거나, 방향을 반대로 바꿀 수 있는데, 그 방향은 패닝의 방향입니다. 이 명세가 규범적으로 정의하지 않는 것은 제스처와 동작의 구현 방식이므로, 사용자 에이전트가 결정할 사항은 두 번째 터치(이 터치가 두 번째 "플링" 또는 현재 패닝에 대한 반대 동작으로 해석되기 전)가 포인터 이벤트를 발생시키는지 아니면 발생시키지 않는지입니다.
참고
touch-action은 임베디드 브라우징 컨텍스트까지 적용되거나 캐스케이드되지 않습니다. 예를 들어, touch-action을 <iframe>에 적용하더라도 패닝 및 확대/축소를 위한 직접 조작 상호작용의 동작에는 아무런 영향을 주지 않으며, 이는 <iframe> 자체 내부에서의 동작입니다.

7.2 지원되는 직접 조작 동작 결정

사용자가 요소와 상호작용할 때 사용하는 것이 직접 조작 포인터라면(예를 들어, 터치스크린에서의 터치나 스타일러스), 해당 입력의 효과는 다음에 따라 결정됩니다: touch-action 속성의 값과 요소의 기본 직접 조작 동작, 그리고 그 조상의 해당 동작이며, 구체적으로는 다음과 같습니다:

참고
일부 사용자 에이전트는 패닝 및 확대/축소 상호작용을 지원하며, 여기에는 동시에 여러 개의 포인터(예: 멀티터치)가 관여합니다. touch-action을 처리하거나 연관 짓는 방법은 동시에 여러 포인터의 값에 대한 것으로서 이 명세의 범위를 벗어납니다.

7.3 touch-action 값의 세부 사항

touch-action 속성은 뷰포트 패닝 및 확대/축소와 관련된 직접 조작 동작을 다룬다. 텍스트 선택/강조 또는 링크 및 폼 컨트롤 활성화와 같은 추가적인 사용자 에이전트 동작은 이 CSS 속성의 영향을 받아서는 안 된다.

참고
"패닝"과 "스크롤링"이라는 용어는 동의어로 간주한다(더 정확히 말하면 "패닝"은 직접 조작 입력을 사용하는 "스크롤링"이다). 패닝/스크롤링을 트리거하는 상호작용이나 제스처, 또는 auto나 none 값에 대한 동작을 트리거하는 상호작용이나 제스처를 정의하는 것은 이 명세의 범위를 벗어난다.
auto
사용자 에이전트는 요소에서 시작되는 뷰포트의 패닝 및 확대/축소와 관련된 허용된 모든 직접 조작 동작을 고려할 수 있다.
none
요소에서 시작되는 직접 조작 상호작용은 뷰포트 패닝 및 확대/축소와 관련된 동작을 트리거해서는 안 된다.
pan-x
pan-left
pan-right
pan-y
pan-up
pan-down
사용자 에이전트는 나열된 모든 값으로 지정된 방향 중 하나에서 시작하는 패닝을 목적으로 하는 경우에만 요소에서 시작되는 직접 조작 상호작용을 고려할 수 있다. 패닝이 시작된 후에는 반대 방향으로 시작하는 패닝이 허용되지 않더라도 사용자가 방향을 반대로 바꿀 수 있다. 반면 패닝이 단일 축으로 제한된 경우(예: pan-x 또는 pan-y)에는 패닝 중에 축을 변경할 수 없다.
manipulation
사용자 에이전트는 패닝 및 연속적인 확대/축소(예: 핀치 줌)를 목적으로 하는 경우에만 요소에서 시작되는 직접 조작 상호작용을 고려할 수 있지만, 정해진 시간 내에 여러 번 활성화해야 하는 다른 관련 동작(예: 두 번 탭하여 확대/축소, 또는 두 번 탭한 뒤 길게 눌러 한 손가락으로 확대/축소)을 트리거해서는 안 된다.
참고
추가 touch-action 값은 구현체에서 흔히 사용되며, 다음에 정의되어 있습니다: [COMPAT].
참고
touch-action 속성은 다음 두 CSS 속성을 모두 지원하는 요소에만 적용됩니다: width와 height 속성(참조: [CSS21]). 이 제한은 사용자 에이전트의 최적화를 돕도록 설계되었으며, 대상은 저지연 직접 조작 패닝 및 확대/축소입니다. 요소 중에서 기본적으로 지원되지 않는 예로는 <span>과 같은 비대체 인라인 요소가 있으며, 작성자는 display CSS 속성을 다음과 같은 값으로 설정할 수 있습니다: block처럼 width와 height를 지원하는 값입니다. 향후 명세에서는 이 API를 모든 요소로 확장할 수 있습니다.
참고

방향별 패닝 값은 일부 오버스크롤 동작을 사용자 지정하는 데 유용합니다. 예를 들어, 간단한 당겨서 새로고침 효과를 구현하려면 문서의 touch-action을 pan-x pan-down으로 설정할 수 있으며, 이는 스크롤 위치가 0일 때이고, 그 외에는 pan-x pan-y로 설정할 수 있습니다. 이렇게 하면 포인터 이벤트 핸들러에서 위쪽 방향의 패닝/스크롤 동작을 정의할 수 있으며, 이는 문서의 맨 위에서 시작하는 동작입니다.

방향별 패닝 값은 컴포넌트를 구성하는 데도 사용할 수 있으며, 이 컴포넌트가 구현하는 것은 사용자 지정 패닝으로, 포인터 이벤트 처리를 이용하여 네이티브로 스크롤되는 요소 안에서 수행합니다(또는 그 반대의 구성입니다). 예를 들어, 이미지 캐러셀은 pan-y를 사용하여 포인터 이벤트 수신을 보장할 수 있으며, 그 대상은 모든 가로 패닝 작업이고 문서의 세로 패닝은 방해하지 않습니다. 캐러셀이 맨 오른쪽 끝에 도달하면 touch-action을 다음 값으로 변경할 수 있습니다: pan-y pan-right. 이렇게 하면 이후 경계를 넘어서는 스크롤 작업으로 스크롤할 수 있는 대상은 가능한 경우 뷰포트 내의 문서입니다. 패닝/스크롤 작업의 동작을 변경하는 것은 불가능하며, 이는 작업이 진행 중인 동안에 해당합니다.

참고
패닝 및 확대/축소를 위한 일부 기본 직접 조작 동작을 비활성화하면 가능해질 수 있는 것은 사용자 에이전트가 다른 동작에 더 빠르게 응답하는 것입니다. 예를 들어, auto에서는 사용자 에이전트가 일반적으로 click 전에 300ms의 지연을 추가하여 두 번 탭 제스처가 처리될 수 있도록 합니다. 이러한 경우, 명시적으로 touch-action: none 또는 touch-action: manipulation을 설정하면 이 지연이 사라집니다. 방법에 관해서는 다음에 유의하세요: 탭 또는 두 번 탭 제스처를 판별하는 방법은 이 명세의 범위에서 벗어납니다.
예제 2: 모든 직접 조작 동작 금지
<div style="touch-action: none;">
    이 요소는 그렇지 않으면 패닝 또는 확대/축소로 이어지는 모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
</div>
예제 3: 수평 패닝만 허용
<div style="touch-action: pan-x;">
    이 요소는 수평 방향으로 패닝하지 않을 때 포인터 이벤트를 수신한다.
</div>
예제 4: 패닝 및 확대/축소를 위한 직접 조작 동작을 허용하지 않는 자식 영역
<div style="overflow: auto;">
    <div style="touch-action: none;">
        이 요소는 그렇지 않으면 패닝 또는 확대/축소로 이어지는 모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
    </div>
    <div>
        이 요소에서의 직접 조작 상호작용은 부모를 조작하는 데 사용될 수 있다.
    </div>
</div>
예제 5: 패닝 및 확대/축소를 위한 직접 조작 동작을 허용하지 않는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y;">
        <div style="touch-action: pan-x;">
            이 요소는 수평 패닝만 허용하지만 중간 조상
            (이 요소와 스크롤 가능한 요소 사이)은 수직 패닝만 허용하므로
            모든 직접 조작 상호작용에 대한 포인터 이벤트를 수신한다.
            따라서 패닝/확대/축소를 위한 직접 조작 동작은
            사용자 에이전트가 처리하지 않는다.
        </div>
    </div>
</div>
예제 6: 패닝 및 확대/축소에 허용되는 직접 조작 동작을 제한하는 중간 부모
<div style="overflow: auto;">
    <div style="touch-action: pan-y pan-left;">
        <div style="touch-action: pan-x;">
            이 요소는 왼쪽으로 패닝하지 않을 때 포인터 이벤트를 수신한다.
        </div>
    </div>
</div>

8. 포인터 캡처

8.1 소개

이 섹션은 비규범적이다.

포인터 캡처를 사용하면 특정 포인터의 이벤트(모든 호환성 마우스 이벤트 포함)를 포인터 위치의 일반적인 히트 테스트 결과가 아닌 특정 요소로 재지정할 수 있다. 이는 사용자 정의 슬라이더 컨트롤(예: [HTML] <input type="range"> 컨트롤과 유사한 경우)과 같은 시나리오에서 유용하다. 포인터 캡처를 슬라이더 썸 요소에 설정하면 포인터가 썸에서 벗어나더라도 사용자가 컨트롤을 앞뒤로 슬라이드할 수 있다.

사용자 정의 볼륨 슬라이더
그림 6 썸 요소를 앞뒤로 슬라이드하여 값을 선택하는 사용자 정의 슬라이더 컨트롤의 예. 썸에서 pointerdown이 발생한 후 포인터 캡처를 사용하면 포인터가 썸에서 벗어나더라도 사용자가 썸을 슬라이드할 수 있다.

8.2 포인터 캡처 설정

포인터 캡처는 element.setPointerCapture(pointerId) 메서드를 호출하여 Element 유형의 element에 설정한다. 이 메서드가 호출되면 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. 메서드의 인수로 제공된 pointerId가 활성 포인터 중 어느 것과도 일치하지 않으면 "NotFoundError" DOMException을 발생시킨다.
  2. pointer를 주어진 pointerId로 지정된 활성 포인터로 둔다.
  3. element가 연결된 상태가 아니면 [DOM], "InvalidStateError" DOMException을 발생시킨다.
  4. element의 노드 문서 [DOM]에 잠긴 요소([PointerLock] pointerLockElement)가 있는 동안 이 메서드가 호출되면 "InvalidStateError" DOMException을 발생시킨다.
  5. pointer가 활성 버튼 상태가 아니거나 element의 노드 문서가 pointer의 활성 문서가 아니면 이 단계를 종료한다.
  6. 지정된 pointerId에 대해 대기 중인 포인터 캡처 대상 재정의를 이 메서드가 호출된 Element로 설정한다.
참고
포인터 캡처를 설정하거나 해제하는 호출이 이루어졌을 때 이전 설정 또는 해제 호출이 대기 상태라면(참조: 처리: 대기 중인 포인터 캡처), 두 번째 호출이 성공하면 첫 번째 호출을 덮어쓰며, 그렇지 않으면 첫 번째 호출이 계속 유효합니다. 이는 다음을 해제하려는 시도가 실패한 경우에도 마찬가지입니다: 암묵적 포인터 캡처. 해당 시도가 이루어지는 곳은 pointerdown 리스너입니다.

8.3 포인터 캡처 해제

포인터 캡처는 element.releasePointerCapture(pointerId) 메서드를 호출하여 요소에서 명시적으로 해제한다. 이 메서드가 호출되면 사용자 에이전트는 다음 단계를 실행해야 한다:

  1. 메서드의 인수로 제공된 pointerId가 활성 포인터 중 어느 것과도 일치하지 않고, 이 단계가 포인터 캡처의 암시적 해제의 결과로 호출된 것이 아니라면 "NotFoundError" DOMException을 발생시킨다.
  2. 지정된 pointerId를 가진 Element에 대해 hasPointerCapture가 false이면, 이 단계를 종료한다.
  3. 지정된 pointerId에 대해 설정되어 있다면 대기 중인 포인터 캡처 대상 재정의를 지운다.
참고
포인터 캡처 설정 섹션의 참고를 참조한다.

8.4 암시적 포인터 캡처

이동 및 확대·축소를 위한 직접 조작 상호작용을 구현하는 입력은 (예: 터치스크린에서의 터치 또는 스타일러스 입력) 모든 setPointerCapture가 대상 요소에서 pointerdown 리스너가 호출되기 직전에 호출된 것과 정확히 동일하게 동작하는 것이 권장됩니다(SHOULD). hasPointerCapture API를 사용하여 (예를 들어 pointerdown 리스너에서) 이러한 동작이 발생했는지 확인할 수 있습니다. 다음 포인터 이벤트가 발생하기 전에 해당 포인터에 대해 releasePointerCapture가 호출되지 않으면 gotpointercapture 이벤트가 대상에 (일반적인 방식으로) 디스패치되어 포인터 캡처가 활성화되었음을 나타냅니다.

참고
이는 다음 명세와의 호환성을 깨뜨리는 변경입니다: [PointerEvents]. 하지만 기존 콘텐츠의 대다수에는 영향을 주지 않습니다. 일반적인 플랫폼 UX 관례에 부합할 뿐 아니라, 이러한 암묵적 캡처 설계는 사용자 에이전트의 성능 최적화를 가능하게 합니다. 이 최적화를 통해 터치 이동 이벤트에서 히트 테스트를 호출할 필요가 없어지며, 개발자의 명시적인 옵트인 없이도 가능합니다(기존에 널리 쓰이는 네이티브 및 웹 API의 성능 특성과 일치하며, 그 대상은 터치 입력입니다).
참고
또한 사용자 에이전트는 암묵적 포인터 캡처 동작을 구현할 수 있으며, 그 대상은 모든 입력 장치이며, 범위 입력 컨트롤과 같은 특정 UI 위젯에서 적용됩니다(손가락의 움직임이 조금 상호작용 중에 폼 컨트롤 자체의 바깥으로 벗어나는 것을 허용합니다).

8.5 포인터 캡처의 암시적 해제

다음 이벤트를 발생시킨 직후(pointerup 또는 pointercancel 이벤트), 사용자 에이전트가 반드시 지워야 하는 것은 대기 중인 포인터 캡처 대상 재정의입니다. 이는 다음 pointerId에 해당하며, 이 식별자는 pointerup 또는 pointercancel 이벤트 중 방금 디스패치된 이벤트의 것입니다. 그런 다음 대기 중인 포인터 캡처 처리 단계를 실행하여 lostpointercapture를 필요한 경우에 발생시킵니다. 다음 절차를 실행한 후에는(대기 중인 포인터 캡처 처리 단계), 포인터가 호버를 지원한다면, 사용자 에이전트는 반드시 추가로 필요한 해당 경계 이벤트를 보내야 합니다. 이는 캡처되지 않은 포인터의 현재 위치를 반영하기 위한 것입니다.

포인터 캡처 대상 재정의가 더 이상 연결되어 있지 않다면 [DOM], 해당 포인터 캡처 대상 재정의에 대해 권장되는 동작은 문서로 설정하는 것입니다.

대기 중인 포인터 캡처 대상 재정의가 더 이상 연결되어 있지 않다면 [DOM], 해당 대기 중인 포인터 캡처 대상 재정의 노드에 대해 권장되는 동작은 이를 지우는 것입니다.

참고
앞의 두 문단에 따라 발생하는 이벤트는 lostpointercapture 이벤트이며, 캡처된 포인터에 해당하는 이 이벤트는 문서에서 발생합니다. 이 이벤트가 발생하는 시점은 다음 대기 중인 포인터 캡처 처리 중이며, 캡처 노드가 제거된 후입니다.

포인터 잠금 [PointerLock]이 요소에 성공적으로 적용되면, 사용자 에이전트는 반드시 다음 메서드가 호출된 것처럼 단계를 실행해야 합니다: releasePointerCapture 메서드. 이는 캡처하도록 설정되었거나 캡처 대기 중인 요소가 있는 경우에 해당합니다.

9. 병합 및 예측 이벤트

참고
이 명세는 사용자 에이전트가 포인터 이동 데이터를 어떻게 병합하거나 예측해야 하는지 정의하지 않는다. 이 정보에 접근하기 위한 API만 규정한다.

9.1 병합된 이벤트

성능상의 이유로 사용자 에이전트는 포인터의 측정 가능한 속성 (예: 좌표, 압력, 접선 압력, 기울기, 비틀림 또는 접촉 형상)이 갱신될 때마다 pointermove 이벤트를 전송하지 않도록 선택할 수 있다. 대신 여러 변경을 하나의 pointermove 또는 pointerrawupdate 이벤트로 병합 (결합/합치기)할 수 있다. 이 접근 방식은 사용자 에이전트가 수행해야 하는 이벤트 처리량을 줄이는 데 도움이 되지만, 특히 빠르고 큰 움직임의 경우 포인터 위치를 추적할 때 세분성과 정확도가 자연스럽게 감소한다. getCoalescedEvents 메서드를 사용하면 애플리케이션이 원시의 병합되지 않은 위치 변경에 접근할 수 있다. 이를 통해 포인터 이동 데이터를 더 정밀하게 처리할 수 있다. 예를 들어 그리기 애플리케이션에서는 병합되지 않은 이벤트를 사용하여 포인터의 실제 움직임에 더 가깝게 일치하는 부드러운 곡선을 그릴 수 있다.

병합된 점과 병합되지 않은 점을 보여 주는 곡선의 확대 보기
그림 7 그리기 애플리케이션의 곡선 예 — pointermove 이벤트의 병합된 좌표(회색 점)만 사용하면 곡선이 눈에 띄게 각지고 들쭉날쭉하지만, getCoalescedEvents()가 제공하는 더 세분화된 점(빨간색 원)을 사용하여 동일한 선을 그리면 포인터 움직임을 더 부드럽게 근사할 수 있다.

PointerEvent에는 연결된 병합된 이벤트 목록(0개 이상의 PointerEvent 목록)이 있다. 신뢰할 수 있는 pointermove 및 pointerrawupdate 이벤트의 경우 이 목록은 해당 이벤트로 병합된 모든 PointerEvent의 시퀀스이다. "부모"인 신뢰할 수 있는 pointermove 및 pointerrawupdate 이벤트는 이러한 병합된 이벤트의 누적을 나타내지만 추가 처리가 적용될 수 있다(예: 디스플레이 재생률에 맞추기 위해). 따라서 이러한 이벤트의 병합된 이벤트 목록에는 항상 최소 하나의 이벤트가 포함된다. 그 밖의 모든 신뢰할 수 있는 이벤트 유형에서는 빈 목록이다. 신뢰할 수 없는 이벤트의 병합된 이벤트 목록은 생성자에 전달된 값으로 초기화된다.

참고
신뢰할 수 있는 부모 이벤트는 병합된 이벤트의 요약 또는 집계이므로 개발자는 부모 이벤트 또는 모든 병합된 이벤트 중 하나만 처리하면 되며 둘 다 처리할 필요는 없다.
참고
병합된 이벤트 목록을 포함하는 신뢰할 수 있는 이벤트가 JavaScript에서 다시 디스패치되면 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만 병합된 이벤트 목록의 동일한 비트는 원래의 true 값에서 변경되지 않는다.

신뢰할 수 있는 이벤트의 병합된 이벤트 목록에 있는 이벤트는 다음을 가진다:

예제 7: 병합된 이벤트 목록을 사용하는 기본 캔버스 그리기 애플리케이션
<style>
    /* 사용자 에이전트 고유의 직접 조작 동작(예: 패닝 또는 확대/축소)을 비활성화하여
    캔버스 요소의 모든 이벤트가 대신 애플리케이션에 전달되도록 한다. */

    canvas { touch-action: none; }
</style>

<canvas id="drawSurface" width="500px" height="500px" style="border:1px solid black;"></canvas>

<script>
    const canvas = document.getElementById("drawSurface"),
    context = canvas.getContext("2d");

    canvas.addEventListener("pointermove", (e)=> {

        if (e.getCoalescedEvents) {
            for (let coalesced_event of e.getCoalescedEvents()) {
                paint(coalesced_event); // 모든 원시/병합되지 않은 점을 그린다
            }
        } else {
            paint(e); // 최종 병합된 점을 그린다
        }
    });

    function paint(event) {
        if (event.buttons>0) {
            context.fillRect(event.clientX, event.clientY, 5, 5);
        }
    }

</script>
참고
PointerEvent의 속성은 병합된 이벤트 목록의 이벤트를 가장 잘 나타내는 방식으로 초기화된다. 사용자 에이전트가 이를 수행해야 하는 구체적인 방법은 이 명세에서 다루지 않는다.

디스패치된 이 모든 이벤트의 순서는 원래 이벤트의 실제 순서와 일치해야 한다. 예를 들어 pointerdown 이벤트가 병합된 pointermove 이벤트의 디스패치를 발생시키는 경우 사용자 에이전트는 먼저 특정 pointerId의 모든 병합된 이벤트를 포함하는 하나의 pointermove 이벤트를 디스패치한 다음 pointerdown 이벤트를 디스패치해야 한다.

참고

다음은 증가하는 timeStamp 값과 함께 실제로 발생한 이벤트와 사용자 에이전트가 디스패치한 이벤트의 예이다:

실제 이벤트 디스패치된 이벤트
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=1) 좌표 변경 pointerrawupdate (pointerId=1), 병합된 이벤트 1개 포함
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=1) 좌표 변경 pointerrawupdate (pointerId=1), 병합된 이벤트 1개 포함
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=1) 버튼 누름 pointermove (pointerId=1), 병합된 이벤트 2개 포함
pointermove (pointerId=2), 병합된 이벤트 4개 포함
pointerdown (pointerId=1), 병합된 이벤트 0개 포함
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=2) 좌표 변경 pointerrawupdate (pointerId=2), 병합된 이벤트 1개 포함
포인터(pointerId=1) 버튼 해제 pointermove (pointerId=2), 병합된 이벤트 2개 포함
pointerup (pointerId=1), 병합된 이벤트 0개 포함

9.2 예측된 이벤트

일부 사용자 에이전트에는 일련의 확인된 포인터 이동 후 현재 제스처의 이전 이벤트와 이동 속도/궤적을 기반으로 미래 포인터 이동의 위치가 어디일지 예측할 수 있는 내장 알고리즘이 있다. 애플리케이션은 getPredictedEvents 메서드를 사용하여 이 정보를 활용하고, 인지되는 지연 시간을 줄이기 위해 예측된 위치까지 추측하여 "미리 그린" 다음 실제 점을 받으면 이러한 예측된 점을 버릴 수 있다.

병합된 점을 사용하여 그린 선과 예측된 미래 점
그림 8 그리기 애플리케이션에서 선의 예(왼쪽 아래에서 오른쪽 위로 그리는 제스처의 결과). pointermove 이벤트의 병합된 좌표를 사용하며, 사용자 에이전트가 예측한 미래 점(회색 원)을 보여 준다.

PointerEvent에는 연결된 예측된 이벤트 목록(0개 이상의 PointerEvent 목록)이 있다. 신뢰할 수 있는 pointermove 이벤트의 경우 이 목록은 사용자 에이전트가 미래에 해당 이벤트 뒤에 이어질 것으로 예측하는 PointerEvent의 시퀀스이다. 그 밖의 모든 신뢰할 수 있는 이벤트 유형에서는 빈 목록이다. 신뢰할 수 없는 이벤트의 예측된 이벤트 목록은 생성자에 전달된 값으로 초기화된다.

참고

pointerrawupdate 이벤트는 비어 있지 않은 병합된 이벤트 목록을 가질 수 있지만, 성능상의 이유로 예측된 이벤트 목록은 일반적으로 빈 목록이다.

참고
예측된 이벤트 목록을 포함하는 신뢰할 수 있는 이벤트가 JavaScript에서 다시 디스패치되면 이벤트 디스패치 알고리즘은 이벤트의 isTrusted 비트를 false로 설정하지만 예측된 이벤트 목록의 동일한 비트는 원래의 true 값에서 변경되지 않는다.

목록의 이벤트 수와 현재 타임스탬프에서 얼마나 먼지는 사용자 에이전트 및 사용자 에이전트가 사용하는 예측 알고리즘에 의해 결정된다.

신뢰할 수 있는 이벤트의 예측된 이벤트 목록에 있는 이벤트는 다음을 가진다:

참고

저자는 다음 포인터 이벤트가 디스패치될 때까지만 예측된 이벤트를 유효한 예측으로 간주해야 한다. 사용자 에이전트가 얼마나 먼 미래의 이벤트를 예측하는지에 따라 일반 포인터 이벤트가 하나 이상의 예측된 이벤트의 타임스탬프보다 먼저 디스패치될 수 있다.

예제 8: 병합된 이벤트 및 예측된 이벤트를 사용한 그리기의 개념적 접근 방식

let predicted_points = [];
window.addEventListener("pointermove", function(event) {
    // 이전에 그린 예측된 점을 지운다.
    for (let e of predicted_points.reverse()) {
        clearPoint(e.pageX, e.pageY);
    }

    // 마지막으로 수신한 이벤트 이후 실제로 발생한 움직임을 그린다.
    for (let e of event.getCoalescedEvents()) {
        drawPoint(e.pageX, e.pageY);
    }

    // 인지되는 지연 시간을 줄이기 위해 현재 예측된 점을 그린다.
    predicted_points = event.getPredictedEvents();
    for (let e of predicted_points) {
        drawPoint(e.pageX, e.pageY);
    }
});

9.3 병합된 이벤트 목록 및 예측된 이벤트 목록 채우기 및 유지

신뢰할 수 있는 PointerEvent가 생성되면 사용자 에이전트는 병합된 이벤트 목록 및 예측된 이벤트 목록의 각 이벤트에 대해 다음 단계를 실행하는 것이 좋다:

  1. 이벤트의 pointerId, pointerType, isPrimary 및 isTrusted를 "부모" 포인터 이벤트의 각각 해당하는 속성과 일치하도록 설정한다.
  2. 이벤트의 cancelable 및 bubbles를 false로 설정한다(이 이벤트는 절대로 독립적으로 디스패치되지 않기 때문).
  3. 이벤트의 병합된 이벤트 목록 및 예측된 이벤트 목록을 빈 목록으로 설정한다.
  4. 다른 모든 속성을 기본 PointerEvent 값으로 초기화한다.

신뢰할 수 있는 PointerEvent의 target이 변경되면 사용자 에이전트는 병합된 이벤트 목록 및 예측된 이벤트 목록의 각 이벤트에 대해 다음을 수행하는 것이 좋다:

  1. 이벤트의 target을 "부모" 포인터 이벤트의 target과 일치하도록 설정한다.

10. 마우스 이벤트와의 호환성 매핑

오늘날 존재하는 웹 콘텐츠의 대다수는 Mouse Events만을 대상으로 코딩되어 있다. 다음에서는 이 콘텐츠와의 호환성을 위해 사용자 에이전트가 일반적인 포인터 입력을 마우스 이벤트에 매핑할 수 있는 알고리즘을 설명한다.

마우스 이벤트와의 호환성 매핑은 이 명세의 선택 사항인 기능이다. 사용자 에이전트는 기존 레거시 콘텐츠와 최상의 호환성을 제공하기 위해 이 기능을 지원하는 것이 권장된다.

참고

개괄적으로, 호환성 마우스 이벤트는 각각에 대응하는 포인터 이벤트와 "교차하여" 발생하도록 의도되었습니다. 그러나 이 특정 순서는 필수가 아니며, 사용자 에이전트가 구현하는 호환성 마우스 이벤트의 디스패치는 선택적으로 지연하거나 묶어서 수행할 수 있습니다. 단, 마우스 이벤트의 상대적인 순서는 일관되게 유지되어야 합니다.

특히 터치스크린 입력의 경우, 사용자 에이전트가 선택적으로 적용할 수 있는 것은 제스처 인식을 위한 추가 휴리스틱입니다(작성자가 다음을 통해 명시적으로 억제하지 않는 한: touch-action). 일련의 이벤트가 pointerdown 이벤트와 pointerup 이벤트 사이에 발생하는 동안, 제스처 인식은 다음 이벤트까지 기다려야 할 수도 있습니다: pointerup 이벤트. 이를 통해 제스처를 감지하거나 무시할 수 있습니다. 따라서 전체 시퀀스의 호환성 마우스 이벤트가 함께 디스패치되는 시점은 마지막 pointerup 이벤트 이후일 수 있습니다. 이는 사용자 에이전트가 상호작용이 특정 제스처를 의도한 것이 아니라고 판단한 경우입니다. 이러한 세부적인 사용자 에이전트의 제스처 인식 방식은 이 명세에서 정의하지 않으며, 구현마다 다를 수 있습니다.

호환성 마우스 이벤트 지원 여부에 관계없이, 사용자 에이전트는 반드시 항상 click, auxclick 및 contextmenu 이벤트를 지원해야 합니다. 그 이유는 이 이벤트들이 PointerEvent 유형이며, 따라서 다음에 해당하지 않기 때문입니다: 호환성 마우스 이벤트. 포인터 이벤트 중에 preventDefault를 호출해도 절대로 영향을 주어서는 안 되는 대상은 click, auxclick 또는 contextmenu의 발생 여부입니다.

참고

이러한 고수준 이벤트 중 일부(예: contextmenu, focus, blur)와 포인터 이벤트 사이의 상대적인 순서는 정의되어 있지 않으며 사용자 에이전트마다 다릅니다. 예를 들어, 일부 사용자 에이전트에서는 contextmenu가 보통 다음 이벤트 뒤에 발생합니다: pointerup. 반면 다른 사용자 에이전트에서는 보통 다음 이벤트보다 먼저 발생합니다: pointerup 또는 pointercancel. 또한 어떤 상황에서는 대응하는 포인터 이벤트 없이 발생할 수도 있습니다(예: 키보드 상호작용의 결과).

또한 사용자 에이전트는 자체적인 휴리스틱을 적용하여 다음 이벤트를 발생시킬지 결정할 수 있습니다: click, auxclick 또는 contextmenu 이벤트. 일부 사용자 에이전트는 동일한 유형의 다른 포인터(주 포인터가 아닌 포인터)가 있거나 다른 유형의 주 포인터가 있는 경우 이 이벤트들을 발생시키지 않을 수 있습니다. 사용자 에이전트는 특정 동작이 "명확한" 탭, 클릭 또는 길게 누르기가 아니라고 판단할 수 있습니다(예를 들어, 터치스크린에서 손가락으로 상호작용하는 동안 손가락이 접촉한 상태에서 지나치게 많이 움직이는 화면 상호작용인 경우). 이때 click, auxclick 또는 contextmenu 이벤트를 발생시키지 않을 수 있습니다. 이러한 사용자 에이전트 동작의 측면은 이 명세에서 정의하지 않으며, 구현마다 다를 수 있습니다.

달리 명시되지 않는 한, 매핑된 모든 마우스 이벤트에 권장되는 대상은 동일한 대상, 즉 각각에 대응하는 포인터 이벤트의 대상입니다. 다만 해당 대상이 더 이상 자신의 ownerDocument 트리에 참여하지 않는 경우는 제외합니다. 이 경우 마우스 이벤트는 원래 대상의 조상 노드(트리에서 제거된 시점을 기준으로) 중 여전히 자신의 ownerDocument 트리에 참여하는 가장 가까운 노드에서 발생하는 것이 좋습니다. 이는 새 대상 노드를 기반으로 마우스 이벤트를 위한 새 이벤트 경로가 구성됨을 의미합니다.

작성자는 특정 호환성 마우스 이벤트의 생성을 방지할 수 있으며, 이를 위해 취소할 이벤트는 pointerdown 이벤트입니다.

마우스 이벤트는 포인터가 눌린 상태일 때만 방지할 수 있습니다. 호버 중인 포인터(예: 아무 버튼도 누르지 않은 마우스)의 마우스 이벤트는 방지할 수 없습니다.

mouseover, mouseout, mouseenter 및 mouseleave 이벤트는 절대로 방지되지 않습니다(포인터가 눌린 상태라도 마찬가지입니다).

호환성 마우스 이벤트를 방지할 수 없는 경우는 포인터 이벤트의 EventListener가 다음과 같이 설정된 경우입니다: passive [DOM].

10.1 레거시 마우스 포인터의 유효 위치 추적

오직 주 포인터만 호환성 마우스 이벤트를 생성할 수 있지만, 여러 주 포인터가 동시에 활성화되어 각각 자신의 호환성 마우스 이벤트를 생성할 수 있습니다. MouseEvents에 의존하는 스크립트와의 호환성을 위해, 마우스 전이 이벤트(mouseover, mouseout, mouseenter 및 mouseleave)에 권장되는 동작은 단일 레거시 마우스 입력의 이동을 시뮬레이션하는 것입니다. 이는 모든 이벤트 대상의 진입/이탈 상태가 유효함을 의미합니다. 사용자 에이전트에 권장되는 방법은 이를 보장하기 위해 레거시 마우스 포인터의 유효 위치를 문서에서 다음과 같이 유지하는 것입니다.

다음 이벤트를 발생시키기 직전의 처리입니다: pointerdown, pointerup 또는 pointermove 이벤트 또는 pointerleave 이벤트(발생 대상: window). 사용자 에이전트에 권장되는 동작은 다음 단계를 실행하는 것입니다:

  1. T를 다음 이벤트의 대상으로 둡니다: pointerdown, pointerup 또는 pointermove 이벤트(디스패치 중인 이벤트). pointerleave 이벤트의 경우에는 T를 미설정 상태로 둡니다.
  2. T와 현재 레거시 마우스 포인터의 유효 위치가 모두 미설정 상태이거나 둘이 같으면, 이 단계를 종료합니다.
  3. mouseover, mouseout, mouseenter 및 mouseleave 이벤트를 마우스 이벤트에 따라 디스패치하며, 이는 마우스가 현재 레거시 마우스 포인터의 유효 위치에서 T로 이동하는 경우에 해당합니다. 현재 레거시 마우스 포인터의 유효 위치나 T의 미설정 값은 창 밖의 마우스 위치로 간주합니다.
  4. 레거시 마우스 포인터의 유효 위치를 T로 설정합니다.
참고

레거시 마우스 포인터의 유효 위치는 포인터 전환 이벤트(pointerover, pointerout, pointerenter 및 pointerleave)를 해당 레거시 마우스 전환 이벤트 (mouseover, mouseout, mouseenter 및 mouseleave)에 항상 직접 매핑할 수는 없다는 사실을 모델링한다. 다음 애니메이션은 두 개의 주 포인터를 하나의 레거시 마우스 입력으로 조정하기 위해 사용자 에이전트가 포인터 전환 이벤트보다 더 많은 레거시 마우스 전환 이벤트를 디스패치해야 하는 경우를 보여 준다.

그림 9 동시에 존재하는 마우스 포인터(흰색 커서)와 터치 포인터(흰색 "손" 커서)로 인해 단일 레거시 마우스 입력 (주황색 커서)이 두 포인터 사이를 이동한다.

이 애니메이션에서 마우스 클릭과 터치 탭 사이의 시간 구간에 유의한다. 버튼 1은 pointerout 이벤트를 받지 않는다("실제" 마우스 포인터가 이 구간 동안 버튼 사각형을 벗어나지 않았기 때문). 하지만 터치 탭으로 레거시 마우스 포인터의 유효 위치가 버튼 2로 이동할 때 버튼 1은 mouseout 이벤트를 받는다. 마찬가지로 터치 탭과 마우스가 버튼 1을 떠나기 직전 사이의 시간 구간 동안 버튼 1은 같은 이유로 pointerover 이벤트를 받지 않지만, 레거시 마우스 포인터의 유효 위치가 버튼 1 내부로 다시 이동하면 버튼 1은 mouseover 이벤트를 받는다.

10.2 호버를 지원하는 장치에 대한 매핑

사용자 에이전트가 호버를 지원하는 장치의 포인터 이벤트를 디스패치하려 할 때마다, 권장되는 동작은 다음 단계를 실행하는 것입니다:

  1. 디스패치할 포인터 이벤트의 isPrimary 속성이 false이면 해당 포인터 이벤트를 디스패치하고 이 단계를 종료합니다.
  2. 디스패치할 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나 pointerleave 이벤트(발생 대상: window)라면, 호환성 마우스 전이 이벤트를 다음에 설명된 대로 디스패치합니다: 레거시 마우스 포인터의 유효 위치 추적.
  3. 포인터 이벤트를 디스패치합니다.
  4. 디스패치된 포인터 이벤트가 pointerdown이고 이벤트의 취소 플래그가 설정되어 있으면, PREVENT MOUSE EVENT 플래그를 이 pointerType에 대해 설정합니다.
  5. PREVENT MOUSE EVENT 플래그가 설정되어 있지 않고(이 pointerType에 대해), 디스패치된 포인터 이벤트가 다음 중 하나라면:
    • pointerdown이면, 다음 이벤트를 발생시킵니다: mousedown 이벤트.
    • pointermove이면, 다음 이벤트를 발생시킵니다: mousemove 이벤트.
    • pointerup이면, 다음 이벤트를 발생시킵니다: mouseup 이벤트.
    • pointercancel이면, mouseup 이벤트를 window에서 발생시킵니다.
  6. 디스패치된 포인터 이벤트가 pointerup 또는 pointercancel이면, PREVENT MOUSE EVENT 플래그를 이 pointerType에 대해 지웁니다.

10.3 호버를 지원하지 않는 장치에 대한 매핑

대부분의 터치스크린과 같은 일부 장치는 활성 상태가 아닐 때 좌표(또는 좌표 집합)에 호버하는 것을 지원하지 않는다. 마우스 이벤트를 대상으로 작성된 기존 콘텐츠의 상당수는 마우스가 이벤트를 생성한다고 가정하므로 일반적으로 다음과 같은 특성이 참이라고 가정한다:

참고
호버는 마우스를 위해 설계된 콘텐츠에서 UI 요소의 표시 여부를 전환하는 데 사용되기도 한다 (예: "호버 메뉴"). 이러한 콘텐츠는 흔히 호버를 지원하지 않는 장치와 호환되지 않는다. 이 명세는 이 시나리오와의 호환성을 위한 매핑이나 동작을 정의하지 않는다. 이는 이 명세의 향후 버전에서 고려될 것이다.

따라서 사용자 에이전트는 이러한 유형의 입력 장치에 대해 다른 매핑을 제공해야 한다. 사용자 에이전트가 호버를 지원하지 않는 장치에 대해 포인터 이벤트를 디스패치할 때마다 다음 단계를 실행하는 것이 좋다:

  1. 디스패치할 포인터 이벤트의 isPrimary 속성이 false이면 해당 포인터 이벤트를 디스패치하고 이 단계를 종료합니다.
  2. 디스패치할 포인터 이벤트가 pointerover이고 pointerdown 이벤트가 이 포인터에 대해 아직 디스패치되지 않았다면, mousemove 이벤트를 발생시킵니다(레거시 마우스 전용 코드와의 호환성을 위해).
  3. 디스패치할 포인터 이벤트가 pointerdown, pointerup 또는 pointermove 이벤트이거나 pointerleave 이벤트(발생 대상: window)라면, 호환성 마우스 전이 이벤트를 다음에 설명된 대로 디스패치합니다: 레거시 마우스 포인터의 유효 위치 추적.
  4. 포인터 이벤트를 디스패치합니다.
  5. 디스패치된 포인터 이벤트가 pointerdown이고 이벤트의 취소 플래그가 설정되어 있으면, PREVENT MOUSE EVENT 플래그를 이 pointerType에 대해 설정합니다.
  6. PREVENT MOUSE EVENT 플래그가 설정되어 있지 않고(이 pointerType에 대해), 디스패치된 포인터 이벤트가 다음 중 하나라면:
    • pointerdown이면, 다음 이벤트를 발생시킵니다: mousedown 이벤트.
    • pointermove이면, 다음 이벤트를 발생시킵니다: mousemove 이벤트.
    • pointerup이면, 다음 이벤트를 발생시킵니다: mouseup 이벤트.
    • pointercancel이면, mouseup 이벤트를 window에서 발생시킵니다.
  7. 디스패치된 포인터 이벤트가 pointerup 또는 pointercancel이면, PREVENT MOUSE EVENT 플래그를 이 pointerType에 대해 지웁니다.

사용자 에이전트가 터치 이벤트(다음에 정의됨: [TOUCH-EVENTS]) 및 포인터 이벤트를 모두 지원한다면, 사용자 에이전트는 절대로 다음 두 가지를 모두 생성해서는 안 됩니다: 이 절에 설명된 호환성 마우스 이벤트와 폴백 마우스 이벤트(다음에 개략적으로 설명됨: [TOUCH-EVENTS]).

참고

요소를 활성화하는 동작(click)에 사용되는 주 포인터가 호버를 지원하지 않는 경우(예: 터치스크린의 한 손가락), 일반적으로 다음과 같은 이벤트 시퀀스가 생성됩니다:

  1. mousemove
  2. pointerover
  3. pointerenter
  4. mouseover
  5. mouseenter
  6. pointerdown
  7. mousedown
  8. 0개 이상의 pointermove 및 mousemove 이벤트가 발생하며, 발생 횟수는 포인터의 움직임에 따라 달라집니다.
  9. pointerup
  10. mouseup
  11. pointerout
  12. pointerleave
  13. mouseout
  14. mouseleave
  15. click

그러나 다음 pointerdown 이벤트의 취소 플래그가 이 상호작용 중에 설정되면, 이벤트 시퀀스는 다음과 같습니다:

  1. mousemove
  2. pointerover
  3. pointerenter
  4. mouseover
  5. mouseenter
  6. pointerdown
  7. 0개 이상의 pointermove 이벤트가 발생하며, 발생 횟수는 포인터의 움직임에 따라 달라집니다.
  8. pointerup
  9. pointerout
  10. pointerleave
  11. mouseout
  12. mouseleave
  13. click

11. 마우스 이벤트 및 인터페이스

마우스 이벤트 모듈은 [HTML401]의 onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove 및 onmouseout 속성에서 비롯되었습니다. 이 이벤트 모듈은 마우스나 트랙볼과 같은 포인팅 입력 장치에서 사용하도록 특별히 설계되었습니다.

DOM Level 2에서 도입되었으며, 이 명세에서 수정되었습니다.

MouseEvent 인터페이스는 마우스 이벤트와 관련된 구체적인 컨텍스트 정보를 제공합니다.

요소가 중첩된 경우, 마우스 이벤트는 항상 가장 깊이 중첩된 요소를 대상으로 합니다.

참고

대상 요소의 조상은 이벤트 버블링을 사용하여 마우스 이벤트의 알림을 받을 수 있습니다. 이는 자신의 자손 요소 내에서 발생하는 이벤트에 해당합니다.

인스턴스를 생성할 인터페이스가 MouseEvent라면, MouseEvent 생성자를 사용하고 선택적으로 MouseEventInit 딕셔너리를 전달합니다.

참고

초기화할 대상이 MouseEvent 객체이고 사용하는 메서드가 initMouseEvent이면, 구현체는 클라이언트 좌표인 clientX와 clientY를 사용하여 다른 좌표를 계산할 수 있습니다. (DOM Level 0 구현에서 노출하는 대상 좌표나 기타 독자적인 속성 등, 예: pageX).

11.1 MouseEvent 인터페이스

WebIDLdictionary MouseEventInit : EventModifierInit {
	long screenX = 0;
	long screenY = 0;
	long clientX = 0;
	long clientY = 0;

	short button = 0;
	unsigned short buttons = 0;
	EventTarget? relatedTarget = null;
};

[Exposed=Window]
interface MouseEvent : UIEvent {
	constructor(DOMString type, optional MouseEventInit eventInitDict = {});
	readonly attribute long screenX;
	readonly attribute long screenY;
	readonly attribute long clientX;
	readonly attribute long clientY;
	readonly attribute long layerX;
	readonly attribute long layerY;

	readonly attribute boolean ctrlKey;
	readonly attribute boolean shiftKey;
	readonly attribute boolean altKey;
	readonly attribute boolean metaKey;

	readonly attribute short button;
	readonly attribute unsigned short buttons;

	readonly attribute EventTarget? relatedTarget;

	boolean getModifierState(DOMString keyArg);
};
screenX

이벤트가 발생한 위치의 수평 좌표로, 화면 좌표계의 원점을 기준으로 합니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

screenY

이벤트가 발생한 위치의 수직 좌표로, 화면 좌표계의 원점을 기준으로 합니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

clientX

이벤트가 발생한 위치의 수평 좌표로, 해당 이벤트와 연결된 뷰포트를 기준으로 합니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

clientY

이벤트가 발생한 위치의 수직 좌표로, 해당 이벤트와 연결된 뷰포트를 기준으로 합니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

layerX

다음 조건 중 하나를 충족하는 가장 가까운 조상 요소로부터의 수평 오프셋입니다: 쌓임 맥락이거나, 위치가 지정된 요소이거나, 다음 작업 중 위치 지정 단계에서 페인트되는 요소: 쌓임 맥락 페인팅.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

layerY

다음 조건 중 하나를 충족하는 가장 가까운 조상 요소로부터의 수직 오프셋입니다: 쌓임 맥락이거나, 위치가 지정된 요소이거나, 다음 작업 중 위치 지정 단계에서 페인트되는 요소: 쌓임 맥락 페인팅.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

ctrlKey

KeyboardEvent의 ctrlKey 속성을 참조하세요.

이 속성의 초기화되지 않은 값은 반드시 false이어야 합니다.

shiftKey

KeyboardEvent의 shiftKey 속성을 참조하세요.

이 속성의 초기화되지 않은 값은 반드시 false이어야 합니다.

altKey

KeyboardEvent의 altKey 속성을 참조하세요.

이 속성의 초기화되지 않은 값은 반드시 false이어야 합니다.

metaKey

KeyboardEvent의 metaKey 속성을 참조하세요.

이 속성의 초기화되지 않은 값은 반드시 false이어야 합니다.

button

마우스 버튼을 누르거나 놓아서 발생하는 마우스 이벤트에서는 button을 반드시 어떤 포인팅 장치 버튼의 상태가 변경되었는지를 나타내는 데 사용해야 합니다.

button 속성의 값은 반드시 다음과 같아야 합니다:

  • 0은 반드시 장치의 주 버튼(일반적으로 왼쪽 버튼 또는 단일 버튼 장치의 유일한 버튼으로, 사용자 인터페이스 컨트롤을 활성화하거나 텍스트를 선택하는 데 사용됨) 또는 초기화되지 않은 값을 나타내야 합니다.
  • 1은 반드시 보조 버튼(일반적으로 마우스 휠과 결합되어 있는 경우가 많은 가운데 버튼)을 나타내야 합니다.
  • 2는 반드시 부 버튼(일반적으로 컨텍스트 메뉴를 표시하는 데 자주 사용되는 오른쪽 버튼)을 나타내야 합니다.
  • 3은 반드시 X1(뒤로) 버튼을 나타내야 합니다.
  • 4는 반드시 X2(앞으로) 버튼을 나타내야 합니다.

일부 포인팅 장치는 더 많은 버튼 상태를 제공하거나 시뮬레이션하며, 2보다 크거나 0보다 작은 값을 선택적으로 사용할 수 있습니다. 이러한 버튼을 나타내기 위한 것입니다.

참고

button의 값은 마우스 버튼을 누르거나 놓아서 발생하는 이벤트가 아니면 갱신되지 않습니다. 이러한 상황에서는 값 0을 왼쪽 버튼으로 해석하지 않고 기본값으로 해석하도록 주의해야 합니다.

참고

일부 기본 동작은 관련된 이벤트(예: mousedown 및 mouseup)에서 사용 중인 특정 마우스 버튼에 따라 달라집니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

buttons

모든 마우스 이벤트에서 buttons는 반드시 현재 눌려 있는 마우스 버튼의 조합을 비트마스크로 나타내는 데 사용해야 합니다.

참고

buttons 속성은 비트 필드입니다. 비트 필드 값에 마스크 값 1을 적용한 결과가 참이면, 주 마우스 버튼이 눌려 있는 것입니다. 마스크 값 2를 비트 필드 값에 적용한 결과가 참이면, 오른쪽 마우스 버튼이 눌려 있는 것입니다. 마스크 값 4를 비트 필드 값에 적용한 결과가 참이면, 보조/가운데 버튼이 눌려 있는 것입니다.

참고

이름은 비슷하지만, buttons 속성과 button 속성의 값은 매우 다릅니다. button의 값이 유효하다고 가정되는 시점은 mousedown / mouseup 이벤트 핸들러 실행 중인 반면, buttons 속성은 마우스 버튼의 상태를 반영합니다. 이는 신뢰된 모든 MouseEvent 객체에 적용됩니다(해당 객체가 디스패치되는 동안). 이 속성은 "현재 활성화된 버튼이 없음" 상태(0)를 나타낼 수 있기 때문입니다.

buttons 속성의 값은 반드시 다음과 같아야 합니다:

  • 0은 반드시 현재 활성화된 버튼이 없음을 나타내야 합니다.
  • 1은 반드시 장치의 주 버튼(일반적으로 왼쪽 버튼 또는 단일 버튼 장치의 유일한 버튼으로, 사용자 인터페이스 컨트롤을 활성화하거나 텍스트를 선택하는 데 사용됨)을 나타내야 합니다.
  • 2는 반드시 부 버튼(일반적으로 컨텍스트 메뉴를 표시하는 데 자주 사용되는 오른쪽 버튼)이 있는 경우 이를 나타내야 합니다.
  • 4는 반드시 보조 버튼(일반적으로 마우스 휠과 결합되어 있는 경우가 많은 가운데 버튼)을 나타내야 합니다.

일부 포인팅 장치는 더 많은 버튼을 제공하거나 시뮬레이션합니다. 이러한 버튼을 나타내려면 값을 반드시 추가되는 버튼마다 두 배로 늘려야 합니다(이진 수열의 8, 16, 32, ... ).

참고

어떤 버튼 값 집합이든 그 합은 고유한 수이므로, 콘텐츠 작성자는 비트 연산을 사용하여 현재 눌린 버튼의 수와 어떤 버튼이 눌렸는지를 판별할 수 있으며, 장치의 마우스 버튼 수가 얼마든 가능합니다. 예를 들어, 값 3은 현재 왼쪽 버튼과 오른쪽 버튼이 모두 눌려 있음을 나타내고, 값 5는 현재 왼쪽 버튼과 가운데 버튼이 모두 눌려 있음을 나타냅니다.

참고

일부 기본 동작은 관련된 이벤트(예: mousedown 및 mouseup)에서 사용 중인 특정 마우스 버튼에 따라 달라집니다.

이 속성의 초기화되지 않은 값은 반드시 0이어야 합니다.

relatedTarget

보조 EventTarget을 식별하는 데 사용되며, 이는 UI 이벤트와 관련된 대상으로서 이벤트 유형에 따라 달라집니다.

이 속성의 초기화되지 않은 값은 반드시 null이어야 합니다.

relatedTarget은 마우스 포인터가 방금 경계를 벗어난 요소로 초기화하거나(다음 mouseover 또는 mouseenter 이벤트의 경우), 마우스 포인터가 경계 안으로 진입하는 요소로 초기화하는 것이 좋습니다(다음 mouseout 또는 mouseleave 또는 focusout 이벤트의 경우). 그 밖의 이벤트에서는 이 값을 할당할 필요가 없습니다(기본값은 null입니다).

getModifierState(keyArg)

키 값을 사용하여 수정자의 상태를 조회합니다.

수정자 키이고 해당 수정자가 활성화되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

DOMString keyArg
KeyboardEvent의 getModifierState() 메서드에서 이 매개변수에 대한 설명을 참조하세요.

구현은 마우스 이벤트를 생성할 때 현재 클릭 횟수를 유지해야 한다. 이는 특정 시간 내에 포인팅 장치 버튼이 연속으로 클릭된 횟수를 나타내는 음이 아닌 정수여야 한다. 횟수가 재설정되는 지연 시간은 환경 구성에 따라 다르다.

11.2 MouseEvent 알고리즘

11.2.1 네이티브 OS 요구사항

이 섹션의 알고리즘은 네이티브 플랫폼 OS가 다음을 제공한다고 가정한다:

이러한 이벤트에 대해 OS는 다음 정보를 제공할 수 있다:

  • 네이티브 OS 데스크톱을 기준으로 한 x,y 마우스 좌표
  • UA의 창 뷰포트를 기준으로 한 x,y 마우스 좌표
  • 현재 누르고 있는 키보드 수정자

11.2.2 Mouse 이벤트 구성

경고

이 절은 수정이 필요합니다.

일반적으로 Event 인터페이스의 생성자나, Event 인터페이스를 상속한 인터페이스의 생성자가 호출되면, 다음에 설명된 단계를 따르는 것이 좋습니다: [DOM]. 그러나 MouseEvent 인터페이스는 추가적인 딕셔너리 멤버를 제공하여 Event 객체의 키 수정자 내부 상태를 초기화할 수 있게 합니다. 구체적으로는 다음 getModifierState() 메서드로 조회하는 내부 상태입니다. 이 절은 [DOM]의 단계를 보완하여, 새로운 MouseEvent 객체를 이러한 선택적 수정자 상태로 초기화할 수 있게 합니다.

아래 알고리즘으로 MouseEvent 또는 이러한 객체에서 파생된 객체를 생성할 수 있도록, 모든 MouseEvent 및 파생 객체는 내부 키 수정자 상태를 가지며, 다음을 사용하여 이를 설정하고 조회할 수 있습니다: 키 수정자 이름. 이 이름은 수정자 키 표에 설명되어 있으며, 해당 표는 [UIEvents-Key]에 있습니다.

다음 단계는 이벤트 생성 알고리즘을 보완하며, 이 알고리즘은 [DOM]에 정의되어 있습니다:

  • 생성 중인 Event가 MouseEvent 객체이거나 이 객체에서 파생된 객체이고, EventModifierInit 인수가 생성자에 제공되었다면, 다음 하위 단계를 실행합니다:
    • 각 EventModifierInit 인수에 대해, 딕셔너리 멤버가 문자열 "modifier"로 시작하면, 키 수정자 이름을 해당 딕셔너리 멤버 이름에서 접두사 "modifier"를 제외한 이름으로 두고, Event 객체의 내부 키 수정자 상태 중 키 수정자 이름과 일치하는 상태를 해당 값으로 설정합니다.

11.2.3 MouseEvent의 전역 상태

경고

이 섹션은 수정이 필요하다.

11.2.3.1 사용자 에이전트 수준 상태

UA는 전체 사용자 에이전트에서 공유되는 다음 값을 유지해야 한다.

마우스 버튼의 현재 상태를 추적하는 마우스 버튼 비트마스크.

11.2.3.2 Window 수준 상태

UA는 Window에서 공유되는 다음 값을 유지해야 한다.

MouseEvent를 전송한 마지막 Element를 추적하는 마지막 마우스 요소 값(초기에는 undefined).

가장 최근의 마우스 이벤트가 전송되었을 때 마지막 마우스 요소의 조상 Element들의 스냅샷을 포함하는 마지막 마우스 DOM 경로 값(초기에는 비어 있음).

11.2.4 MouseEvent의 내부 상태

경고

이 섹션은 수정이 필요하다.

MouseEvent에는 다양한 수정자 키의 상태를 추적하는 데 사용되는 다음 내부 플래그가 있다: shift 플래그, control 플래그, alt 플래그, altgraph 플래그, 그리고 meta 플래그. 해당 수정자 키가 마우스 이벤트 시점에 눌려 있었다면 이러한 플래그가 설정된다.

11.2.5 히트 테스트

경고

이 섹션은 수정이 필요하다.

  1. pos를 뷰포트를 기준으로 한 x,y 좌표로 둔다
  2. pos로 [CSSOM-View]의 elementFromPoint() (pos에서 가장 앞쪽에 있는 DOM 요소)를 반환한다
    참고

    비활성 또는 사용 불가 요소를 고려하려면, 이는 elementsFromPoint()를 호출하고 유효하지 않은 요소를 제외해야 한다.

11.2.6 MouseEvent 초기화

경고

이 섹션은 수정이 필요하다.

event, eventType 및 eventTarget, bubbles, 그리고 cancelable로 MouseEvent를 초기화하려면 다음 단계를 실행한다:

  1. event, eventType, eventTarget, bubbles 및 cancelable로 UIEvent를 초기화한다.
  2. event.screenX를 데스크톱의 원점을 기준으로 이벤트가 발생한 위치의 x 좌표로 설정한다
  3. event.screenY를 데스크톱의 원점을 기준으로 이벤트가 발생한 위치의 y 좌표로 설정한다
  4. event.clientX를 뷰포트의 원점을 기준으로 이벤트가 발생한 위치의 x 좌표로 설정한다
  5. event.clientY를 뷰포트의 원점을 기준으로 이벤트가 발생한 위치의 y 좌표로 설정한다
  6. event로 마우스 이벤트 수정자를 설정한다
  7. event.button을 0으로 설정한다
  8. event.buttons를 마우스 버튼 비트마스크로 설정한다
  9. event로 MouseEvent의 PointerLock 속성을 초기화한다
    이슈 1

    여기에서 PointerLock을 하드코딩하는 대신 이를 위한 훅을 제공해야 한다.

11.2.7 마우스 이벤트 수정자 설정

경고

이 섹션은 수정이 필요하다.

  1. event를 갱신할 MouseEvent로 둔다
  2. 키 수정자 상태에 "Shift"가 포함되어 있으면 event의 shift 플래그를 설정하고, 그렇지 않으면 설정 해제한다
  3. 키 수정자 상태에 "Control"이 포함되어 있으면 event의 control 플래그를 설정하고, 그렇지 않으면 설정 해제한다
  4. 키 수정자 상태에 "Alt"가 포함되어 있으면 event의 alt 플래그를 설정하고, 그렇지 않으면 설정 해제한다
  5. 키 수정자 상태에 "AltGraph"가 포함되어 있으면 event의 altgraph 플래그를 설정하고, 그렇지 않으면 설정 해제한다
  6. 키 수정자 상태에 "Meta"가 포함되어 있으면 event의 meta 플래그를 설정하고, 그렇지 않으면 설정 해제한다
  7. 이벤트의 shift 플래그가 설정되어 있으면 event.shiftKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  8. 이벤트의 control 플래그가 설정되어 있으면 event.ctrlKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  9. 이벤트의 alt 플래그 또는 altgraph 플래그가 설정되어 있으면 event.altKey를 true로 설정하고, 그렇지 않으면 false로 설정한다
  10. 이벤트의 meta 플래그가 설정되어 있으면 event.metaKey를 true로 설정하고, 그렇지 않으면 false로 설정한다

11.2.8 취소 가능한 MouseEvent 생성

경고

이 섹션은 수정이 필요하다.

  1. eventType을 유효한 MouseEvent 유형을 포함하는 DOMString으로 둔다
  2. eventTarget을 이벤트의 EventTarget으로 둔다
  3. bubbles를 true로 둔다
  4. cancelable을 true로 둔다
  5. event를 MouseEvent를 사용하여 이벤트를 생성한 결과로 둔다
  6. event, eventType, eventTarget, bubbles 및 cancelable로 MouseEvent를 초기화한다.
  7. event를 반환한다

11.2.9 취소할 수 없는 MouseEvent 생성

경고

이 섹션은 수정이 필요하다.

  1. eventType을 유효한 MouseEvent 유형을 포함하는 DOMString으로 둔다
  2. eventTarget을 이벤트의 EventTarget으로 둔다
  3. bubbles를 "false"로 둔다
  4. cancelable을 "false"로 둔다
  5. event를 MouseEvent를 사용하여 이벤트를 생성한 결과로 둔다
  6. event, eventType, eventTarget, bubbles 및 cancelable로 MouseEvent를 초기화한다.
  7. event를 반환한다

11.2.10 MouseEvent button 속성 계산

경고

이 섹션은 수정이 필요하다.

이는 MouseEvent의 button 속성에 저장하기에 적합한 버튼 ID를 반환한다.

  1. mbutton을 마우스 버튼을 식별하는 ID로 둔다
  2. mbutton이 주 마우스 버튼이면 0을 반환한다
  3. mbutton이 보조(가운데) 마우스 버튼이면 1을 반환한다
  4. mbutton이 보조 마우스 버튼이면 2를 반환한다
  5. mbutton이 X1(뒤로) 버튼이면 3을 반환한다
  6. mbutton이 X2(앞으로) 버튼이면 4를 반환한다

11.2.11 네이티브에서 MouseEvent 속성 설정

경고

이 섹션은 수정이 필요하다.

  1. event를 초기화할 MouseEvent로 둔다
  2. native를 네이티브 마우스 이벤트로 둔다
    편집자 주

    TODO.

  3. event.type이 [ mousedown, mouseup ] 중 하나이면
    1. mbutton을 어떤 마우스 버튼이 눌렸는지 식별하는 native의 ID로 둔다
    2. event.button을 mbutton으로 MouseEvent button 속성 계산한 결과로 설정한다

11.2.12 네이티브 마우스 다운 처리

경고

이 섹션은 수정이 필요하다.

  1. native를 네이티브 mousedown으로 둔다
  2. mbutton을 어떤 마우스 버튼이 눌렸는지 식별하는 native의 ID로 둔다
  3. 마우스 버튼 비트마스크를 다음과 같이 갱신한다:
    1. mbutton이 주 마우스 버튼이면 0x01 비트를 설정한다
    2. mbutton이 보조 마우스 버튼이면 0x02 비트를 설정한다
    3. mbutton이 보조(가운데) 마우스 버튼이면 0x04 비트를 설정한다
      참고

      다른 버튼은 0x08부터 추가할 수 있다.

  4. target을 native의 뷰포트 상대 좌표로 히트 테스트한 결과로 둔다
  5. event를 "mousedown", target으로 취소 가능한 MouseEvent를 생성한 결과로 둔다
  6. native로 네이티브에서 MouseEvent 속성을 설정한다
  7. 필요한 경우 event를 사용하여 pointerdown 이벤트를 보냅니다.
  8. result를 target에서 event를 디스패치한 결과로 둔다
  9. result가 true이고 target이 포커스 가능한 영역이며 클릭 포커스 가능한 경우
    1. target에서 포커스 단계를 실행한다
  10. mbutton이 보조 마우스 버튼이면
    1. native, target으로 컨텍스트 메뉴를 표시할 수 있음을 실행한다

11.2.13 네이티브 마우스 업 처리

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 mouseup으로 설정합니다
    참고

    mousedown과 mouseup 사이에 다른 마우스 이벤트가 발생할 수 있습니다.

  2. mbutton을 native에서 어떤 마우스 버튼이 눌렸는지를 식별하는 ID로 설정합니다
  3. 마우스 버튼 비트마스크를 다음과 같이 업데이트합니다:
    1. mbutton이 기본 마우스 버튼이면 0x01 비트를 지웁니다
    2. mbutton이 보조 마우스 버튼이면 0x02 비트를 지웁니다
    3. mbutton이 보조(가운데) 마우스 버튼이면 0x04 비트를 지웁니다
  4. target을 native의 뷰포트 상대 좌표를 사용하여 히트 테스트한 결과로 설정합니다
  5. event를 "mouseup", target을 사용하여 취소 가능한 MouseEvent를 생성한 결과로 설정합니다
  6. native를 사용하여 네이티브로부터 MouseEvent 속성을 설정합니다
  7. 필요한 경우 event로 pointerup 이벤트를 전송합니다
  8. target에서 event를 디스패치합니다

11.2.14 네이티브 마우스 클릭 처리

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 마우스 클릭으로 설정합니다
    참고

    플랫폼은 클릭을 생성하는 mouseup에 대해 네이티브 마우스 버튼 놓기를 처리한 직후 이 절차를 호출해야 합니다.

  2. target을 native의 뷰포트 상대 좌표를 사용하여 히트 테스트한 결과로 설정합니다
  3. native와 target을 사용하여 클릭 이벤트를 전송합니다.

11.2.15 click 이벤트 전송

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 mousedown으로 설정합니다
  2. target을 이벤트의 EventTarget으로 설정합니다
  3. mbutton을 1로 설정합니다(기본적으로 주 마우스 버튼)
  4. native가 유효하면
    1. mbutton을 native에서 어떤 마우스 버튼이 눌렸는지 식별하는 ID로 설정합니다
  5. mbutton이 주 마우스 버튼이면 eventType을 "click"으로, 그렇지 않으면 "auxclick"으로 설정합니다
  6. event를 eventType과 target을 사용하여 PointerEvent를 생성한 결과로 설정합니다
  7. native가 유효하면
    1. event와 native를 사용하여 네이티브로부터 MouseEvent 속성을 설정합니다
    2. event.screenX가 정숫값이 아니면 반올림합니다.
    3. event.screenY가 정숫값이 아니면 반올림합니다.
  8. target에서 event를 디스패치합니다
    참고

    PointerEvents를 사용하는 브라우저와 반올림된 좌표에 관한 정보는 pointerevents/100을 참조하세요.

    편집자 주

    모든 "기본 동작"은 디스패치 중 대상의 활성화 동작 알고리즘을 트리거하여 처리됩니다. 따라서 여기서 별도로 처리할 필요가 없습니다. 다만 기존 명세가 다음 항목을 처리하는지 확인해야 합니다: disabled/css-pointer-events/inert/...

    참고

    HTMLelement.click()을 처리하려면 native = null, target = HTMLelement로 이 알고리즘을 호출합니다.

    참고

    키보드로 시작된 클릭을 처리하려면 native = null로 설정하고 target = 현재 포커스된 요소로 이 알고리즘을 호출합니다.

11.2.16 네이티브 마우스 더블 클릭 처리

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 마우스 더블 클릭으로 설정합니다
    참고

    더블 클릭을 생성하는 마우스 클릭의 경우 네이티브 마우스 클릭을 처리한 직후 이 절차를 호출해야 합니다.

  2. mbutton을 native에서 어떤 마우스 버튼이 눌렸는지 식별하는 ID로 설정합니다
  3. mbutton이 주 마우스 버튼이 아니면 반환합니다
  4. target을 native의 뷰포트 상대 좌표를 사용하여 히트 테스트한 결과로 설정합니다
  5. event를 "dblclick"과 target을 사용하여 PointerEvent를 생성한 결과로 설정합니다
  6. event와 native를 사용하여 네이티브로부터 MouseEvent 속성을 설정합니다
  7. event.screenX가 정숫값이 아니면 반올림합니다.
  8. event.screenY가 정숫값이 아니면 반올림합니다.
  9. 디스패치합니다 event를 target에서

11.2.17 네이티브 마우스 이동 처리

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 마우스 이동으로 설정합니다
    문제 2

    이 알고리즘은 PointerEvents의 디스패치에 대해 가정하고 있는데, 이는 현재 명시적으로 규정되어 있지 않기 때문입니다. pointerevents/285가 해결되면 이 알고리즘을 업데이트해야 할 수 있습니다.

  2. target을 native의 뷰포트 상대 좌표를 사용하여 히트 테스트한 결과로 설정합니다
  3. targetDomPath를 target의 포괄적 조상으로 설정합니다
  4. 현재 요소에서 벗어날 때 발생하는 이벤트를 생성합니다:
    1. 마지막 마우스 요소가 정의되어 있고 target과 같지 않으면
      1. mouseout을 "mouseout"과 취소 가능한 MouseEvent를 생성할 때 마지막 마우스 요소를 사용한 결과로 설정합니다
        편집자 주

        TODO: native에서 mouseout의 속성을 설정합니다. +CSSOM 속성.

    2. 필요한 경우 mouseout으로 pointerout 이벤트를 전송합니다
    3. 디스패치합니다 target에서 mouseout을
      참고

      취소되었을 때의 동작을 확인해야 합니다(영향이 없는 것으로 보입니다).

    4. leaveElements를 마지막 마우스 DOM 경로에서 targetDomPath와 공통된 모든 요소를 제거한 복사본으로 설정합니다.
    5. leaveElements의 각 element에 대해 다음을 수행합니다
      편집자 주

      element가 삭제된 경우를 처리해야 합니다. 이동된 경우도 마찬가지입니다. DOM 변경으로 인해 mouseleave 이벤트가 트리거되어야 했을까요? 지금 전송해야 할까요? 무시해야 할까요? 현재 브라우저의 동작을 확인해야 합니다.

      1. mouseleave를 "mouseleave"와 element를 사용하여 취소할 수 없는 MouseEvent를 생성한 결과로 설정합니다
      2. mouseleave.Event.composed를 = false로 설정합니다
        참고

        호환성을 확인해야 합니다: event.composed의 값입니다. 명세에서는 false라고 규정합니다. Chrome/Linux = true입니다. Firefox/Linux = false입니다.

      3. 필요한 경우 mouseleave로 pointerleave 이벤트를 전송합니다
      4. result를 element에서 mouseleave를 디스패치한 결과로 설정합니다
  5. 새 요소에 진입할 때 발생하는 이벤트를 생성합니다:
    1. target이 마지막 마우스 요소가 아니면
      1. mouseover를 "mouseover"와 target을 사용하여 취소 가능한 MouseEvent를 생성한 결과로 설정합니다
        편집자 주

        TODO: native에서 mouseout의 속성을 설정합니다. +CSSOM 속성.

      2. 필요한 경우 mouseover로 pointerover 이벤트를 전송합니다
      3. 디스패치합니다 target에서 mouseout을
        참고

        취소되었을 때의 동작을 확인해야 합니다(영향이 없는 것으로 보입니다).

      4. enterElements를 targetDomPath에서 마지막 마우스 DOM 경로와 공통된 모든 요소를 제거한 복사본으로 설정합니다
      5. enterElements의 각 element에 대해 다음을 수행합니다
        참고

        element가 삭제되거나 이동된 경우를 처리해야 합니다.

        1. mouseenter를 "mouseenter"와 element를 사용하여 취소할 수 없는 MouseEvent를 생성한 결과로 설정합니다
        2. mouseenter.Event.composed를 = false로 설정합니다
          참고

          호환성을 확인해야 합니다: event.composed의 값입니다. 명세에서는 false라고 규정합니다. Chrome/Linux = true입니다. Firefox/Linux = false입니다.

        3. 필요한 경우 mouseenter로 pointerenter 이벤트를 전송합니다
          참고

          섀도 DOM 요소에 대한 호환성을 확인해야 합니다. Chrome/Linux에서는 이 이벤트가 해당 요소와 섀도 루트에서 발생합니다.

        4. result를 element에서 mouseenter를 디스패치한 결과로 설정합니다
      6. 마지막 마우스 요소를 target으로 설정합니다
      7. 마지막 마우스 DOM 경로를 targetDomPath로 설정합니다
  6. mousemove를 "mousemove"와 element를 사용하여 취소 가능한 MouseEvent를 생성한 결과로 설정합니다
  7. mousemove에 대한 PointerLock 속성을 설정합니다
  8. 필요한 경우 mousemove로 pointermove 이벤트를 전송합니다
  9. 디스패치합니다 element에서 mousemove를

11.2.18 컨텍스트 메뉴를 표시할 수 있음

경고

이 절은 수정이 필요합니다.

  1. native를 네이티브 mousedown 또는 포인터 이벤트로 설정합니다
  2. target을 이벤트의 EventTarget으로 설정합니다
    1. menuevent를 "contextmenu"와 target을 사용하여 PointerEvent를 생성한 결과로 설정합니다
    2. native가 유효하면
      1. native를 사용하여 네이티브로부터 MouseEvent 속성을 설정합니다
    3. result를 target에서 menuevent를 디스패치한 결과로 설정합니다
    4. result가 true이면 사용자 에이전트의 컨텍스트 메뉴를 표시합니다
참고

키보드로 트리거된 컨텍스트 메뉴를 처리하려면 native = null, target = 현재 포커스된 요소로 설정하여 이 알고리즘을 호출합니다.

11.3 Mouse 이벤트 순서

이 명세에서 정의된 특정 마우스 이벤트는 서로에 대해 정해진 순서로 발생해야 한다. 다음은 포인팅 장치의 커서가 요소 위로 이동할 때 발생해야 하는 이벤트 시퀀스를 보여 준다:

# 이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 요소 A 안으로 이동한다...
2 mouseover A
3 mouseenter A
4 mousemove A 여러 mousemove 이벤트
포인팅 장치가 요소 A 밖으로 이동한다...
5 mouseout A
6 mouseleave A

포인팅 장치가 요소 A 안으로 이동한 다음 중첩된 요소 B 안으로 이동하고 다시 밖으로 이동할 때 다음 이벤트 시퀀스가 발생해야 한다:

이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 요소 A 안으로 이동한다...
2 mouseover A
3 mouseenter A
4 mousemove A 여러 mousemove 이벤트
포인팅 장치가 중첩된 요소 B 안으로 이동한다...
5 mouseout A
6 mouseover B
7 mouseenter B
8 mousemove B 여러 mousemove 이벤트
포인팅 장치가 요소 B에서 A로 이동한다...
9 mouseout B
10 mouseleave B
11 mouseover A
12 mousemove A 여러 mousemove 이벤트
포인팅 장치가 요소 A 밖으로 이동한다...
13 mouseout A
14 mouseleave A

경우에 따라 CSS를 사용하여 요소를 시각적으로 겹칠 수 있다. 다음 예에서 A, B, C로 표시된 세 요소는 모두 웹 페이지에서 동일한 크기와 절대 위치를 가진다. DOM에서 요소 C는 B의 자식이고, B는 A의 자식이다:

서로 완전히 겹쳐 쌓인 세 요소의 그래픽 표현. 가장 아래 요소는 A로 표시되고 가장 위 요소는 C로 표시됨
그림 10 서로 완전히 겹쳐 쌓인 세 요소와 포인팅 장치가 그 스택 위로 이동하는 모습을 나타낸 그래픽 표현.

포인팅 장치가 요소 스택 바깥에서 C로 표시된 요소로 이동한 다음 다시 밖으로 이동하면 다음 일련의 이벤트가 발생해야 한다:

이벤트 유형 요소 참고
1 mousemove
포인팅 장치가 스택의 최상위 요소인 요소 C 안으로 이동한다
2 mouseover C
3 mouseenter A
4 mouseenter B
5 mouseenter C
6 mousemove C 여러 mousemove 이벤트
포인팅 장치가 요소 C 밖으로 이동한다...
7 mouseout C
8 mouseleave C
9 mouseleave B
10 mouseleave A
참고

mouseover/mouseout 이벤트는 한 번만 발생하지만, mouseenter/mouseleave 이벤트는 세 번(각 요소마다 한 번씩) 발생한다.

다음은 포인팅 장치와 연결된 버튼(예: 마우스 버튼 또는 트랙패드)을 요소 위에서 눌렀다가 놓을 때의 일반적인 이벤트 시퀀스이다:

이벤트 유형 참고
1 mousedown
2 mousemove 선택 사항, 여러 이벤트, 일부 제한
3 mouseup
4 click
5 mousemove 선택 사항, 여러 이벤트, 일부 제한
6 mousedown
7 mousemove 선택 사항, 여러 이벤트, 일부 제한
8 mouseup
9 click
10 dblclick
참고

click 또는 dblclick 이벤트가 계속 발생할 수 있는 범위에서 mousedown과 mouseup 이벤트 사이에 허용되는 지연 시간, 정도, 거리 및 mousemove 이벤트의 수는 구현, 장치 및 플랫폼에 따라 다르다. 이러한 허용 오차는 손 떨림과 같은 신체적 장애가 있는 사용자가 포인팅 장치와 상호작용할 때 도움을 줄 수 있다.

각 구현은 적절한 히스테리시스 허용 오차를 결정하지만, 일반적으로 연관된 mousedown 및 mouseup 이벤트의 이벤트 대상이 동일한 요소이고 그 사이에 mouseout 또는 mouseleave 이벤트가 없는 경우 click 및 dblclick 이벤트를 발생시키는 것이 좋고, 연관된 mousedown 및 mouseup 이벤트의 대상이 서로 다른 경우에는 가장 가까운 공통 포괄 조상에서 click 및 dblclick 이벤트를 발생시키는 것이 좋다.

mousedown 이벤트의 대상이 HTML 문서의 body 요소이고, 이에 해당하는 mouseup 이벤트의 대상이 문서 요소인 경우 click 이벤트는 가장 가까운 공통 포괄 조상이므로 문서 요소에 디스패치된다.

대상(예: 대상 요소)이 마우스 이벤트 시퀀스 중에 DOM에서 제거되면 시퀀스의 나머지 이벤트는 해당 요소에서 발생해서는 안 된다.

mousedown 이벤트의 결과로 대상 요소가 DOM에서 제거되면 해당 요소에 대해서는 mouseup, click 또는 dblclick 이벤트나 어떤 기본 활성화 이벤트도 디스패치되지 않는다. 그러나 mouseup 이벤트는 초기 대상 요소가 제거된 후 마우스에 노출된 요소에서 계속 디스패치된다. 마찬가지로 mouseup 이벤트의 디스패치 중에 대상 요소가 DOM에서 제거되면 click 및 후속 이벤트는 디스패치되지 않는다.

11.4 Mouse 이벤트 유형

Mouse 이벤트 유형은 아래에 나열되어 있다. 중첩된 요소의 경우 마우스 이벤트 유형은 항상 가장 깊이 중첩된 요소를 대상으로 한다. 대상 요소의 조상은 버블링을 사용하여 자손 요소 내에서 발생하는 마우스 이벤트에 대한 알림을 받을 MAY.

11.4.1 auxclick

유형 auxclick
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자가 주가 아닌 포인터 버튼을 누르고 놓거나, 그와 같은 동작을 시뮬레이션하는 방식으로 포인터를 활성화하는 경우 auxclick 이벤트 유형은 포인터가 가리키는 최상위 이벤트 대상에 디스패치되어MUST 한다. 마우스 버튼의 작동 방식은 포인터 장치와 환경 구성에 따라 달라지며, 예를 들어 화면 위치나 포인팅 장치 버튼을 누르고 놓는 사이의 지연 시간에 따라 달라질 MAY 있다.

auxclick 이벤트는 주가 아닌 포인터 버튼에 대해서만 발생시키는 것이 좋다(즉, button 값이 0이 아니고, buttons 값이 1보다 큰 경우). 주 버튼 (표준 마우스의 왼쪽 버튼 등)은 auxclick 이벤트를 발생시켜MUST NOT 한다. 주 버튼과 연결된 해당 이벤트는 click을 참조한다.

auxclick 이벤트보다 먼저 동일한 요소에서 mousedown 및 mouseup 이벤트가 발생할 MAY 있으며, 다른 노드 유형 (예: 텍스트 노드) 사이의 변화는 무시한다. 환경 구성에 따라 포인팅 장치 버튼을 누르고 놓는 사이에 mouseover, mousemove 및 mouseout 이벤트 유형 중 하나 이상이 발생하더라도 auxclick 이벤트가 디스패치될 MAY 있다.

auxclick 이벤트 유형의 기본 동작은 이벤트의 대상과 button 또는 buttons 속성 값에 따라 달라진다. auxclick 이벤트 유형의 일반적인 기본 동작은 다음과 같다:

  • 대상에 연결된 활성화 동작이 있는 경우 기본 동작은 해당 활성화 동작을 실행하는 것이어MUST 한다.
예제 9: 가운데 버튼의 auxclick 수신 및 처리
myLink.addEventListener("auxclick", function(e) {
  if (e.button === 1) {
    // 예를 들어 링크를 가운데 클릭할 때 새 탭을 여는
    // 기본 동작을 방지한다.
    e.preventDefault();
    // 앱에 맞는 방식으로 새 탭에서 링크 또는 링크가 아닌 버튼을
    // 여는 것처럼 가운데 버튼 클릭을 처리하기 위한 다른 작업을 수행한다.
    // 탭 표시줄에서 탭을 닫는 것처럼 클릭 동작에서 수행해야 하는
    // 다른 작업도 여기에서 수행할 수 있다.
  }
});
참고

오른쪽 버튼의 경우 auxclick 이벤트는 모든 contextmenu 이벤트 뒤에 디스패치된다. 일부 사용자 에이전트는 컨텍스트 메뉴가 표시되는 동안 모든 입력 이벤트를 삼키므로 이러한 시나리오에서는 애플리케이션이 auxclick을 사용할 수 없을 수 있음에 유의한다. 자세한 설명은 예제 10을 참조한다.

예제 10: 오른쪽 버튼의 auxclick 수신 및 처리
myDiv.addEventListener("contextmenu", function(e) {
  // 이 호출은 컨텍스트 메뉴가 표시되어
  // 페이지의 이벤트 수신을 방해하지 않도록 한다.
  e.preventDefault();
});
myDiv.addEventListener("auxclick", function(e) {
  if (e.button === 2) {
    // 앱 내부에서 사용자 정의 컨텍스트 메뉴를 여는 것처럼
    // 오른쪽 버튼 클릭을 처리하기 위한 다른 작업을 수행한다.
  }
});

11.4.2 click

유형 click
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자가 주 포인터 버튼을 누르고 놓거나, 그와 같은 동작을 시뮬레이션하는 방식으로 포인터를 활성화하는 경우 click 이벤트 유형은 포인터가 가리키는 최상위 이벤트 대상에 디스패치되어MUST 한다. 마우스 버튼의 작동 방식은 포인터 장치와 환경 구성에 따라 달라지며, 예를 들어 화면 위치나 포인팅 장치 버튼을 누르고 놓는 사이의 지연 시간에 따라 달라질 MAY 있다.

click 이벤트는 주 포인터 버튼에 대해서만 발생시키는 것이 좋다(즉, button 값이 0이고, buttons 값이 1인 경우). 보조 버튼 (표준 마우스의 가운데 또는 오른쪽 버튼 등)은 click 이벤트를 발생시켜MUST NOT 한다. 주가 아닌 버튼과 연결된 해당 이벤트는 auxclick을 참조한다.

click 이벤트보다 먼저 mousedown 및 mouseup 이벤트가 동일한 요소에서 발생할 MAY 있으며, 다른 노드 유형 (예: 텍스트 노드) 사이의 변화는 무시한다. 환경 구성에 따라 포인팅 장치 버튼을 누르고 놓는 사이에 mouseover, mousemove 및 mouseout 이벤트 유형 중 하나 이상이 발생하더라도 click 이벤트가 디스패치될 MAY 있다. 또한 click 이벤트 뒤에 dblclick 이벤트가 이어질 MAY 있다.

사용자가 큰 line-height가 적용된 <p> 요소의 텍스트 노드 자식에서 마우스 버튼을 누른 뒤, 마우스를 약간 움직여 더 이상 텍스트가 포함된 영역 위에는 있지 않지만 여전히 해당 <p> 요소의 포함 블록 안에 있는 경우 (즉, 포인터가 동일한 텍스트 블록의 줄 사이에 있지만 텍스트 노드 자체 위에는 있지 않은 경우), 이후 마우스 버튼을 놓으면 사용자가 동일한 요소의 범위 내에 머물렀으므로 일반적인 시간적 히스테리시스 범위 내라면 click에 대해 여전히 click 이벤트가 발생할 가능성이 높다. 사용자 에이전트가 생성한 마우스 이벤트는 텍스트 노드에 디스패치되지 않는다는 점에 유의한다.

포인터 장치와 연결되는 것 외에도 click 이벤트 유형은 요소 활성화의 일부로 디스패치되어MUST 한다.

참고

최대한의 접근성을 위해 콘텐츠 저자는 사용자 정의 컨트롤의 활성화 동작을 정의할 때 click 이벤트 유형을 사용하는 것이 권장되며, mousedown 또는 mouseup처럼 장치에 더 종속적인 다른 포인팅 장치 이벤트 유형을 사용하는 것은 권장되지 않는다. click 이벤트 유형은 포인터 장치(예: 마우스)에서 유래했지만 이후 구현 개선을 통해 이러한 연결을 넘어 확장되었으며, 요소 활성화를 위한 장치 독립적인 이벤트 유형으로 간주할 수 있다.

click 이벤트 유형의 기본 동작은 이벤트의 대상과 button 또는 buttons 속성 값에 따라 달라진다. click 이벤트 유형의 일반적인 기본 동작은 다음과 같다:

  • 대상에 연결된 활성화 동작이 있는 경우 기본 동작은 해당 활성화 동작을 실행하는 것이어MUST 한다.
  • 대상이 포커스 가능하면 기본 동작은 해당 요소에 문서 포커스를 부여하는 것이어MUST 한다.

11.4.3 contextmenu

유형 contextmenu
인터페이스 PointerEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 컨텍스트 메뉴를 호출하기 전에 이 이벤트를 디스패치해MUST 한다.

contextmenu 이벤트가 마우스 오른쪽 버튼에 의해 트리거되는 경우 contextmenu 이벤트는 mousedown 이벤트 뒤에 디스패치되어MUST 한다.

참고

플랫폼에 따라 contextmenu 이벤트는 mouseup 이벤트보다 먼저 또는 나중에 디스패치될 수 있다.

11.4.4 dblclick

유형 dblclick
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치의 주 버튼이 요소 위에서 두 번 클릭될 때 이 이벤트를 디스패치해MUST 한다. 더블 클릭의 정의는 환경 구성에 따라 달라지지만, 이벤트 대상은 mousedown, mouseup 및 dblclick 사이에서 동일해MUST 한다. 클릭과 더블 클릭이 동시에 발생하는 경우 이 이벤트 유형은 click 이벤트 유형 뒤에 디스패치되어MUST 하며, 그렇지 않은 경우 mouseup 이벤트 유형 뒤에 디스패치되어야 한다.

click 이벤트와 마찬가지로 dblclick 이벤트는 주 포인터 버튼에 대해서만 발생시키는 것이 좋다. 보조 버튼은 dblclick 이벤트를 발생시켜MUST NOT 한다.

참고

click 이벤트를 취소해도 dblclick 이벤트 발생에는 영향을 주지 않는다.

click 이벤트 유형과 마찬가지로 dblclick 이벤트 유형의 기본 동작은 이벤트의 대상과 button 또는 buttons 속성 값에 따라 달라진다. dblclick 이벤트 유형의 일반적인 기본 동작은 click 이벤트 유형의 기본 동작과 같다.

11.4.5 mousedown

유형 mousedown
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치 버튼이 요소 위에서 눌릴 때 이 이벤트를 디스패치해MUST 한다.

참고

많은 구현은 mousedown 이벤트를 사용하여 컨텍스트에 따라 달라지는 다양한 기본 동작을 시작한다. 이러한 기본 동작은 이 이벤트가 취소되면 방지할 수 있다. 이러한 기본 동작에는 이미지 또는 링크에 대한 드래그 앤 드롭 상호작용 시작, 텍스트 선택 시작 등이 포함될 수 있다. 또한 일부 구현은 mousedown 이벤트가 디스패치되는 시점에 가운데 마우스 버튼이 눌려 있으면 활성화되는 마우스 기반 패닝 기능을 제공한다.

11.4.6 mouseenter

유형 mouseenter
인터페이스 MouseEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소 또는 그 자손 요소 중 하나의 경계 안으로 이동할 때 이 이벤트를 디스패치해MUST 한다. 또한 사용자 에이전트는 요소 또는 그 자손 중 하나가 이동하여 주 포인팅 장치 아래에 위치하게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseover와 유사하지만 버블링되지 않으며, 포인팅 장치가 요소에서 그 자손 요소 중 하나의 경계로 이동할 때는 디스패치되어MUST NOT 한다는 점에서 다르다.

참고

이 이벤트 유형과 CSS :hover 의사 클래스 [CSS2] 사이에는 유사점이 있다. mouseleave 이벤트 유형도 참조한다.

11.4.7 mouseleave

유형 mouseleave
인터페이스 MouseEvent
버블링 아니요
취소 가능 아니요
합성 아니요
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소와 그 모든 자손 요소의 경계 밖으로 이동할 때 이 이벤트를 디스패치해MUST 한다. 또한 사용자 에이전트는 요소 또는 그 자손 중 하나가 이동하여 더 이상 주 포인팅 장치 아래에 있지 않게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseout과 유사하지만 버블링되지 않으며, 포인팅 장치가 요소와 모든 자식 요소의 경계를 떠날 때까지 디스패치되어MUST NOT 한다는 점에서 다르다.

참고

이 이벤트 유형과 CSS :hover 의사 클래스 [CSS2] 사이에는 유사점이 있다. mouseenter 이벤트 유형도 참조한다.

11.4.8 mousemove

유형 mousemove
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소 위에서 이동할 때 이 이벤트를 디스패치해MUST 한다. 포인팅 장치가 이동하는 동안의 이벤트 발생 빈도는 구현, 장치 및 플랫폼에 따라 다르지만, 지속적인 포인터 장치 이동에서는 각 마우스 이동마다 단일 이벤트만 발생시키는 대신 연속된 여러 mousemove 이벤트를 발생시키는 것이 SHOULD 좋다. 구현은 응답성과 성능의 균형을 맞추기 위한 최적의 빈도를 결정하는 것이 권장된다.

참고

브라우저와 같은 일부 구현 환경에서는 사용자가 드래그 작업을 시작했고(예: 마우스 버튼이 눌려 있음) 포인팅 장치가 사용자 에이전트의 경계를 벗어난 경우에도 mousemove 이벤트가 계속 발생할 수 있다.

참고

이 이벤트는 이전에 DOM 레벨 2 Events에서 취소할 수 없는 것으로 명시되었지만, 사용자 에이전트 간 기존 상호운용성을 반영하기 위해 변경되었다.

11.4.9 mouseout

유형 mouseout
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소의 경계 밖으로 이동하거나 요소가 이동하여 더 이상 주 포인팅 장치 아래에 있지 않게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseleave와 유사하지만 버블링되며, 포인팅 장치가 요소에서 그 자손 요소 중 하나의 경계로 이동할 때 디스패치되어MUST 한다는 점에서 다르다.

참고

mouseover 이벤트 유형도 참조한다.

11.4.10 mouseover

유형 mouseover
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치가 요소의 경계 안으로 이동하거나 요소가 이동하여 주 포인팅 장치 아래에 위치하게 될 때 이 이벤트를 디스패치해MUST 한다. 이 이벤트 유형은 mouseenter와 유사하지만 버블링되며, 같은 이벤트 리스너 인스턴스의 대상인 조상 요소를 가진 요소의 경계 안으로 포인터 장치가 이동할 때 디스패치되어MUST 한다는 점에서 다르다.

참고

mouseout 이벤트 유형도 참조한다.

11.4.11 mouseup

유형 mouseup
인터페이스 MouseEvent
버블링 예
취소 가능 예
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 포인팅 장치 버튼이 요소 위에서 놓일 때 이 이벤트를 디스패치해MUST 한다.

참고

브라우저와 같은 일부 구현 환경에서는 포인팅 장치가 사용자 에이전트의 경계를 벗어난 경우에도 mouseup 이벤트가 디스패치될 수 있다. 예를 들어 사용자가 마우스 버튼을 누른 상태에서 드래그 작업을 시작한 경우이다.

12. 휠 이벤트 및 인터페이스

휠은 하나 이상의 공간 차원에서 회전할 수 있으며 포인터 장치와 연결될 수 있는 장치이다. 좌표계는 환경 구성에 따라 달라진다.

사용자의 환경은 수직 스크롤을 y축을 따른 회전과, 수평 스크롤을 x축을 따른 회전과, 확대/축소를 z축을 따른 회전과 연결하도록 구성되어 있을 수 있다.

WheelEvent 객체의 deltaX, deltaY 및 deltaZ 속성은 각각의 축을 따라 픽셀, 줄 또는 페이지 단위로 측정한 값을 나타낸다. 보고되는 측정값은 환경별 알고리즘이 휠 장치의 실제 회전/이동을 적절한 값과 단위로 변환한 후 제공된다.

참고

사용자의 환경 설정은 휠 장치의 실제 회전/이동을 서로 다른 방식으로 해석하도록 사용자 정의할 수 있다. 일반적인 톱니형 마우스 휠을 한 번 움직이면 162픽셀의 측정값이 생성될 수 있다 (162는 단지 예시 값이며 실제 값은 사용자 에이전트의 현재 화면 크기에 따라 달라질 수 있다). 그러나 사용자는 기본 환경 설정을 변경하여 마우스 휠의 속도를 높이고 이 수치를 증가시킬 수 있다. 또한 일부 마우스 휠 소프트웨어는 가속(휠을 더 빠르게 회전/이동할수록 각 측정값의 델타가 커짐) 또는 서브픽셀 회전 측정까지 지원할 수 있다. 이 때문에 저자는 한 사용자 에이전트에서 주어진 회전량이 모든 사용자 에이전트에서 동일한 델타 값을 생성한다고 가정할 수 없다.

deltaX, deltaY 및 deltaZ 속성 값의 부호(양수 또는 음수)는 실제 휠 장치의 움직임이 동일한 방향으로 회전/이동하는 동안 wheel 이벤트가 여러 번 디스패치되더라도 일관되어MUST 한다. 사용자 에이전트가 wheel 이벤트의 기본 동작으로 스크롤하는 경우 델타의 부호는 양의 X, Y 및 Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리 및 가장 먼 깊이(사용자에서 멀어지는 방향)를 향하는 오른손 좌표계에 따라 주어지는 것이 SHOULD 좋다.

참고

개별 사용자 에이전트는 환경과 하드웨어 구성에 따라 휠에서 동일한 물리적 사용자 상호작용을 서로 다르게 해석할 수 있다. 예를 들어 트랙패드 가장자리를 위에서 아래로 수직으로 스와이프하는 동작은 페이지를 아래로 스크롤하거나 페이지를 위로 패닝하기 위한 휠 동작으로 해석될 수 있다(즉, 각각 양수 또는 음수 deltaY 값이 생성될 수 있다).

사용자 에이전트는 첫 번째 휠 이벤트가 발생할 때 휠 이벤트 트랜잭션을 생성MUST 하여, 구현별 시간 범위 내의 모든 후속 휠 이벤트가 동일한 요소를 대상으로 할 수 있도록 해야 한다. 휠 이벤트 트랜잭션은 하나의 사용자 제스처와 연결된 일련의 휠 이벤트이다. 휠 이벤트 트랜잭션은 그룹의 첫 번째 휠 이벤트가 발생할 당시의 최상위 이벤트 대상인 연결된 이벤트 대상을 가져MUST 한다.

스크롤 가능한 요소를 대상으로 하는 일련의 휠 이벤트가 자식 요소 위쪽에서 시작되면, 동일한 사용자 제스처에 대한 이후 이벤트는 자식 요소 위에서 발생할 수 있다.

12.1 WheelEvent 인터페이스

WheelEvent 인터페이스는 wheel 이벤트와 관련된 특정 컨텍스트 정보를 제공한다.

WheelEvent 인터페이스의 인스턴스를 생성하려면 WheelEvent 생성자를 사용하고 선택적인 WheelEventInit 딕셔너리를 전달한다.

WebIDLdictionary WheelEventInit : MouseEventInit {
    double deltaX = 0.0;
    double deltaY = 0.0;
    double deltaZ = 0.0;
    unsigned long deltaMode = 0;
    boolean momentum = false;
};

[Exposed=Window]
interface WheelEvent : MouseEvent {
    constructor(DOMString type, optional WheelEventInit eventInitDict = {});
    // DeltaModeCode
    const unsigned long DOM_DELTA_PIXEL = 0x00;
    const unsigned long DOM_DELTA_LINE	= 0x01;
    const unsigned long DOM_DELTA_PAGE	= 0x02;

    readonly attribute double deltaX;
    readonly attribute double deltaY;
    readonly attribute double deltaZ;
    readonly attribute unsigned long deltaMode;
    readonly attribute boolean momentum;
};
DOM_DELTA_PIXEL
델타의 측정 단위는 픽셀이어MUST 한다. 이는 대부분의 운영체제 및 구현 구성에서 가장 일반적인 경우이다.
DOM_DELTA_LINE
델타의 측정 단위는 개별 텍스트 줄이어MUST 한다. 이는 많은 폼 컨트롤에 해당한다.
DOM_DELTA_PAGE
델타의 측정 단위는 페이지여MUST 하며, 단일 화면 또는 구분된 페이지로 정의될 수 있다.
deltaX
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 x축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 x축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값은 0.0이어MUST 한다.
deltaY
wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 y축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 y축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다. 이 속성의 초기화되지 않은 값은 0.0이어MUST 한다.
deltaZ

wheel 이벤트의 기본 동작이 스크롤인 사용자 에이전트에서는, 이벤트가 취소되지 않았을 때 스크롤할 z축 방향의 측정값(픽셀, 줄 또는 페이지 단위)이 값이어MUST 한다. 그렇지 않은 경우 이는 휠 장치의 z축 주위 움직임에 대한 구현별 측정값(픽셀, 줄 또는 페이지 단위)이다.

이 속성의 초기화되지 않은 값은 0.0이어MUST 한다.

WheelEvent 객체의 deltaZ 속성을 초기화한다. 이 속성의 상대적인 양수 값(deltaX 및 deltaY 속성도 마찬가지)은 X, Y 및 Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리, 가장 먼 깊이(사용자에서 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어진다. 음의 상대 값은 각각 반대 방향이다.

deltaMode

deltaMode 속성은 델타 값의 측정 단위를 나타낸다. 기본값은 DOM_DELTA_PIXEL(픽셀)이다.

이 속성은 델타 값의 측정 단위를 나타내기 위해 DOM_DELTA 상수 중 하나로 설정되어MUST 한다. 정확한 측정 방식은 장치, 운영체제 및 애플리케이션 구성에 따라 달라진다.

이 속성의 초기화되지 않은 값은 0이어MUST 한다.

momentum

사용자가 물리적인 스크롤 상호작용을 끝낸 후 (예: 플링 후 트랙패드에서 손가락을 뗀 경우) 스크롤 관성을 시뮬레이션하기 위해 플랫폼이 이 이벤트를 합성했다면 이 속성은 true여야 하고, 그렇지 않으면 false여야 한다.

이 속성의 초기화되지 않은 값은 false이어MUST 한다.

12.2 휠 이벤트 유형

12.3 wheel

유형 wheel
인터페이스 WheelEvent
버블링 예
취소 가능 경우에 따라 다름
합성 예
컨텍스트
(신뢰할 수 있는 이벤트)

사용자 에이전트는 마우스 휠이 어떤 축을 중심으로 회전했거나, 동등한 입력 장치 (예: 마우스 볼, 특정 태블릿 또는 터치패드 등)가 이러한 동작을 에뮬레이션했을 때 이 이벤트를 디스패치해MUST 한다. 플랫폼과 입력 장치에 따라 대각선 휠 델타는 0이 아닌 여러 축을 가진 하나의 wheel 이벤트로 전달되거나, 0이 아닌 각 축마다 별도의 wheel 이벤트로 전달될 MAY 있다.

wheel 이벤트 유형의 일반적인 기본 동작은 표시된 양만큼 문서를 스크롤(또는 일부 경우 확대/축소)하는 것이다. 이 이벤트가 취소되면 구현은 문서를 스크롤하거나 확대/축소해MUST NOT 하며 (또는 이 이벤트 유형과 연결된 다른 구현별 기본 동작을 수행해서는 안 된다).

참고

일부 사용자 에이전트 또는 일부 입력 장치에서는 휠을 돌린 속도가 델타 값에 영향을 줄 수 있으며, 더 빠른 속도는 더 큰 델타 값을 생성한다.

12.3.1 휠 이벤트의 취소 가능성

휠 이벤트에서 preventDefault를 호출하면 스크롤을 방지하거나 중단할 수 있다. 최대의 스크롤 성능을 위해 사용자 에이전트는 스크롤과 관련된 각 휠 이벤트가 취소되는지 확인하기 위해 처리될 때까지 기다리지 않을 수 있다. 이런 경우 사용자 에이전트는 cancelable 속성이 false인 wheel 이벤트를 생성하여 preventDefault로 스크롤을 방지하거나 중단할 수 없음을 나타내는 것이 좋다. 그렇지 않으면 cancelable은 true가 된다.

특히 사용자 에이전트가 이벤트에 대해 비수동 리스너가 없음을 관찰하는 경우에는 취소할 수 없는 wheel 이벤트만 생성하는 것이 좋다.

13. 예제

이 섹션은 비규범적이다.

다음은 저자가 이 명세의 일부 API를 어떻게 사용할 수 있는지 보여 주는 기본 예제이다. 더 구체적인 예제는 이 문서의 관련 섹션에서 제공한다.

예제 11: 기능 감지 및 이벤트 바인딩
/* 포인터 이벤트 또는 기존 터치/마우스 중 하나에 바인딩 */

if (window.PointerEvent) {
    // 포인터 이벤트가 지원되면 포인터 이벤트만 수신한다
    target.addEventListener("pointerdown", function(e) {
        // 필요한 경우 e.pointerType에 따라 별도의 로직을 적용한다
        // 서로 다른 터치/펜/마우스 동작에 대해
        ...
    });
    ...
} else {
    // 기존 터치/마우스 이벤트 핸들러
    target.addEventListener('touchstart', function(e) {
        // 호환성 마우스 이벤트 및 click을 방지한다
        e.preventDefault();
        ...
    });
    ...
    target.addEventListener('mousedown', ...);
    ...
}

// 키보드 처리를 위한 추가 이벤트 리스너
...
예제 12: 사용자의 입력 유형 감지
window.addEventListener("pointerdown", detectInputType);

function detectInputType(event) {
    switch(event.pointerType) {
        case "mouse":
            /* 마우스 입력 감지 */
            break;
        case "pen":
            /* 펜/스타일러스 입력 감지 */
            break;
        case "touch":
            /* 터치 입력 감지 */
            break;
        default:
            /* pointerType이 비어 있음(감지할 수 없음)
            또는 UA별 사용자 정의 유형 */
    }
}
예제 13: 접촉 형상에 맞게 요소 크기 조정
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", checkPointerSize);

function checkPointerSize(event) {
    event.target.style.width = event.width + "px";
    event.target.style.height = event.height + "px";
}
</script>
예제 14: 스크립트에서 신뢰할 수 없는 포인터 이벤트 발생시키기
const event1 = new PointerEvent("pointerover",
  { bubbles: true,
    cancelable: true,
    composed: true,
    pointerId: 42,
    pointerType: "pen",
    clientX: 300,
    clientY: 500
  });
eventTarget.dispatchEvent(event1);

let pointerEventInitDict =
{
  bubbles: true,
  cancelable: true,
  composed: true,
  pointerId: 42,
  pointerType: "pen",
  clientX: 300,
  clientY: 500,
};
const p1 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
const p2 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.coalescedEvents = [p1, p2];
const event2 = new PointerEvent("pointermove", pointerEventInitDict);
eventTarget.dispatchEvent(event2);
예제 15: PointerDown에서 펜 색상 할당
<div style="position:absolute; top:0px; left:0px; width:100px;height:100px;"></div>
<script>
window.addEventListener("pointerdown", assignPenColor);
window.addEventListener("pointermove", assignPenColor);
const colorMap = new Map();

function assignPenColor(event) {
    const uniqueId = event.persistentDeviceId;
    // 고유 ID가 존재하는지 확인한다.
    if (uniqueId == 0) {
        return;
    }
    // 장치에 색상이 할당되었는지 확인한다.
    if (map.has(uniqueId)) {
        return;
    }
    // 장치에 색상을 할당한다.
    let newColor = getNewColor();
    map.set(uniqueId, newColor);
    return newColor;
}

function getNewColor() {
    /* 어떤 색상 값을 반환한다 */
}
</script>

14. 보안 및 개인정보 보호 고려사항

이 부록에서는 포인터 이벤트 구현의 보안 및 개인정보 보호 고려사항을 논의한다. 논의는 이 명세에서 정의한 이벤트 모델, API 및 이벤트의 구현으로 직접 발생하는 보안 및 개인정보 보호 문제로 한정한다.

이 명세에서 정의한 많은 이벤트 유형은 사용자 동작에 응답하여 디스패치된다. 이로 인해 악의적인 이벤트 리스너가 사용자가 일반적으로 기밀로 간주할 정보에 접근할 수 있다. 예를 들어 페이지와 상호작용하는 동안 사용자의 마우스/스타일러스/손가락이 이동한 정확한 경로/움직임 등이 있다.

포인터 이벤트에는 사용자의 장치에서 지원되는 경우 펜 입력을 잡고 있는 각도 또는 기울기, 접촉 표면의 형상, 스타일러스나 터치스크린에 가해지는 압력과 같은 추가 정보가 포함된다. 각도, 기울기, 형상 및 압력에 관한 정보는 사용자의 장치에 있는 센서와 직접 관련되므로 이 명세는 오리진이 이러한 센서에 접근할 수 있도록 한다.

이 센서 데이터와 사용된 입력 메커니즘 유형(마우스, 터치, 펜)을 판단하는 기능은 사용자 또는 사용자의 장치 및 환경의 특성을 추론하는 데 사용될 수 있다. 이러한 추론된 특성과 장치/환경 정보 자체도 민감할 수 있다. 예를 들어 악의적인 사이트가 사용자가 보조 기술을 사용하고 있는지 추가로 추론할 수 있게 할 수 있다. 또한 이 정보는 사용자 프로필을 구축하거나 특정 사용자를 "핑거프린팅"하고 추적하려는 목적으로 잠재적으로 사용될 수 있다.

완화책으로 사용자 에이전트는 사용자가 특정 센서 데이터 (예: 각도, 기울기, 압력)에 대한 접근을 비활성화할 수 있는 기능을 포함하거나, 사용자의 명시적인 동의 후에만 이를 사용할 수 있도록 하는 것을 고려할 수 있다.

이 명세는 저자가 "예측된 이벤트"에 접근할 수 있는 방법을 정의한다. 이 명세 자체는 사용자 에이전트가 예측에 사용해야 하는 알고리즘을 정의하지 않는다. 명세 저자는 알고리즘이 사용자가 현재 수행 중인 제스처와 관련된 이전 포인터 이벤트에만 의존할 것으로 예상한다. 예측 알고리즘의 구체적인 구현이 서로 다른 사이트에 걸친 사용자의 전체 상호작용 기록과 같은 추가 데이터에 의존하지 않도록 보장하는 것은 사용자 에이전트의 책임이다. 이러한 데이터는 사용자에 대한 민감한 정보를 드러내거나 사용자를 "핑거프린팅"하고 추적하는 데 사용될 수 있기 때문이다.

이러한 고려사항 외에도 작업 그룹은 이 명세가 다음과 같다고 본다:

15. 용어집

이 섹션은 비규범적이다.

활성 버튼 상태
포인터의 buttons 속성 값이 0이 아닌 상태. 마우스의 경우 이는 장치에서 적어도 하나의 버튼이 눌린 상태이다. 터치의 경우 디지타이저와 물리적으로 접촉한 상태이다. 펜의 경우 펜이 디지타이저와 물리적으로 접촉했거나 호버 중 적어도 하나의 버튼이 눌린 상태이다.
활성 문서
각 활성 포인터에 대해 해당 포인터의 마지막 이벤트를 수신한 문서.
활성 포인터
이벤트를 생성할 수 있는 모든 터치 접촉, 펜/스타일러스, 마우스 커서 또는 기타 포인터. 특정 포인터(고유한 pointerId로 식별됨)가 문서 내에서 추가 이벤트를 생성할 가능성이 있다면 해당 포인터는 여전히 활성 상태로 간주된다. 예:
  • 장치에 연결된 마우스는 항상 활성 상태이다.
  • 화면의 터치 접촉은 활성 상태로 간주된다.
  • 터치 접촉 또는 펜/스타일러스가 디지타이저의 범위를 벗어나 들어 올려지면 더 이상 활성 상태로 간주되지 않는다.
참고
일부 플랫폼에서는 활성 포인터 집합에 사용자 에이전트를 대상으로 하지 않는 입력(예: 다른 애플리케이션을 대상으로 하는 입력)을 포함하여 장치에 대한 모든 포인터 입력이 포함된다.
접촉 형상
디지타이저에 대한 입력(가장 일반적으로 터치)의 경계 상자. 일반적으로 이는 단일 픽셀보다 포인터 입력 해상도가 거친 장치를 가리킨다. 일부 장치는 이 데이터를 전혀 보고하지 않는다.
델타
WheelEvent 인터페이스를 지원하는 입력 장치 (예: 마우스 휠 또는 터치패드)의 물리적 움직임에 응답하여 사용자 에이전트가 페이지를 스크롤하거나 확대/축소할 것으로 예상되는 양(픽셀, 줄 또는 페이지 단위). 델타 값(예: deltaX, deltaY 또는 deltaZ 속성)은 현재 deltaMode 속성의 컨텍스트에서 해석해야 한다. 휠(또는 다른 장치)의 물리적 움직임과 델타가 양수인지 음수인지의 관계는 환경과 장치에 따라 달라진다. 그러나 사용자 에이전트가 기본 동작으로 스크롤하는 경우 델타의 부호는 양의 X, Y 및 Z축이 각각 문서의 가장 오른쪽 가장자리, 가장 아래쪽 가장자리 및 가장 먼 깊이(사용자에서 멀어지는 방향)를 향하는 오른손 좌표계에 의해 주어진다.
디지타이저
표면이 접촉하거나 가까이 근접한 입력을 감지할 수 있는 입력 감지 장치의 한 유형. 가장 일반적으로 터치 접촉 또는 펜/스타일러스의 입력을 감지하는 표면을 가리킨다.
직접 조작
일부 사용자 에이전트(예: 터치스크린 장치의 브라우저)는 포인터가 컨트롤과 상호작용할 뿐만 아니라 현재 페이지를 직접 패닝하거나 확대/축소하는 데도 사용되어 직접 물리적으로 접촉하는 듯한 착각을 제공하는 "직접 조작" 메타포를 구현한다. 예를 들어 터치스크린 장치의 사용자는 일반적으로 손가락이나 스타일러스를 사용해 페이지를 "잡고" 포인터를 움직여 패닝함으로써 페이지를 직접 조작할 수 있다. 이는 페이지를 "드래그"하는 대신 스크롤바를 사용하여 패닝하는 일반 데스크톱/노트북의 마우스 포인터와 대조된다.
참고
일부 경우 터치패드(노트북에 있는 것과 같은)는 사용자가 터치패드를 "드래그"하여 스크롤할 수 있도록 한다. 그러나 이는 일반적으로 터치패드가 "가짜" 마우스 휠 이벤트를 생성하는 방식으로 이루어지므로 직접 조작으로 간주되지 않는다.
히스테리시스
사용자 경험을 개선하기 위해 위치 또는 시간의 특정 범위 내 입력 값을 허용하는 인간 인터페이스 설계의 기능. 예를 들어 사용자가 마우스 버튼을 더블 클릭하는 데 걸리는 시간의 작은 편차를 허용하는 것은 시간적 히스테리시스이고, 사용자가 자식 메뉴로 이동하면서 부모 창을 마우스로 벗어날 때 중첩 메뉴를 즉시 닫지 않는 것은 위치적 히스테리시스이다.
측정 가능한 속성

측정 가능한 속성은 실수 또는 넓은 도메인의 정수를 사용하여 표현되는 연속적인 포인터 센서 데이터와 관련된 값을 나타낸다. 포인터 이벤트에서는 width, height, pressure, tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle 및 Mouse Event 모델 속성인 screenX, screenY, clientX, clientY가 측정 가능한 속성이다.

반면 pointerId, pointerType, isPrimary 및 Mouse Event 모델 속성인 button, buttons, ctrlKey, shiftKey, altKey, metaKey는 센서 데이터와 관련되지 않으므로 측정 가능한 속성으로 간주되지 않는다.

포인터
마우스, 펜 또는 터치 접촉과 같이 화면의 특정 좌표(또는 좌표 집합)를 대상으로 할 수 있는 입력 장치의 하드웨어 독립적 표현.
회전
WheelEvent 인터페이스를 사용하는 입력 장치의 점진적 변화를 나타내는 표시. 일부 장치에서는 이것이 휠의 실제 회전일 MAY 있으며, 다른 장치에서는 평평한 표면을 따른 이동 또는 특정 버튼에 가해지는 압력일 MAY 있다.
최상위 이벤트 대상
최상위 이벤트 대상은 대상이 될 수 있는 요소 중 렌더링 순서에서 가장 위에 있는 요소여MUST 한다. 그래픽 사용자 인터페이스에서는 사용자의 포인팅 장치 아래에 있는 요소이다. 사용자 인터페이스의 히트 테스트 기능을 사용하여 대상을 결정한다. 히트 테스트와 스태킹 순서에 관한 구체적인 세부 사항은 호스트 언어를 참조한다.

16. 레거시 이벤트 초기화자

이 섹션은 규범적이다. 다음 기능은 폐기되었으며 레거시 소프트웨어와의 호환성이 필요한 사용자 에이전트만 구현하는 것이 좋다. [UIEvents]의 레거시 이벤트 초기화자도 참조한다.

16.1 MouseEvent 인터페이스의 초기화자

WebIDLpartial interface MouseEvent {
	// 이 명세에서 폐기됨
	undefined initMouseEvent(DOMString typeArg,
		optional boolean bubblesArg = false,
		optional boolean cancelableArg = false,
		optional Window? viewArg = null,
		optional long detailArg = 0,
		optional long screenXArg = 0,
		optional long screenYArg = 0,
		optional long clientXArg = 0,
		optional long clientYArg = 0,
		optional boolean ctrlKeyArg = false,
		optional boolean altKeyArg = false,
		optional boolean shiftKeyArg = false,
		optional boolean metaKeyArg = false,
		optional short buttonArg = 0,
		optional EventTarget? relatedTargetArg = null);
};
initMouseEvent(typeArg)
MouseEvent 객체의 속성을 초기화한다. 이 메서드는 UIEvent.initUIEvent()와 동일하게 동작한다.
경고

initMouseEvent 메서드는 폐기되었지만 널리 배포된 구현과의 하위 호환성을 위해 지원된다.

DOMString typeArg
이 매개변수에 대한 설명은 initEvent() 메서드를 참조한다.
boolean bubblesArg
이 매개변수에 대한 설명은 initEvent() 메서드를 참조한다.
boolean cancelableArg
이 매개변수에 대한 설명은 initEvent() 메서드를 참조한다.
Window? viewArg
view를 지정한다. 이 값은 null일 MAY 있다.
long detailArg
detail을 지정한다.
long screenXArg
screenX를 지정한다.
long screenYArg
screenY를 지정한다.
long clientXArg
clientX를 지정한다.
long clientYArg
clientY를 지정한다.
boolean ctrlKeyArg
ctrlKey를 지정한다.
boolean altKeyArg
altKey를 지정한다.
boolean shiftKeyArg
shiftKey를 지정한다.
boolean metaKeyArg
metaKey를 지정한다.
short buttonArg
button을 지정한다.
EventTarget? relatedTargetArg
relatedTarget을 지정한다. 이 값은 null일 MAY 있다.

A. 감사의 말

많은 분이 제안과 권고를 제공해 주셨으며 그중 일부는 이 문서에 반영되었다. 진심으로 감사드린다. 그룹 의장은 다음의 전·현직 그룹 구성원 및 참가자의 기여에 감사를 표한다: Mustaq Ahmed, Arthur Barstow, Ben Boyle, Matt Brubeck, Rick Byers, Marcos Cáceres, Cathy Chan, Bo Cupp, Domenic Denicola, Ted Dinklocker, Adam Ettenberger, Robert Flack, Dave Fleck, Mike Fraser, Ella Ge, Olga Gerchikov, Scott González, Kartikaya Gupta, Dominique Hazael-Massieux, Philippe Le Hégaret, Hayato Ito, Patrick Kettner, Patrick H. Lauke, Scott Low, Sangwhan Moon, Masayuki Nakano, Olli Pettay, Addison Phillips, Alan Pyne, Antoine Quint, Jacob Rossi, Kagami Sascha Rosylight, Doug Schepers, Ming-Chou Shih, Brenton Simpson, Dave Tapuska, Liviu Tinta, Asir Vedamuthu, Lan Wei, Jeffrey Yasskin, Navid Zolghadr.

과거에 마우스 및 휠 이벤트를 관리해 주신 분들께 감사드린다: Gary Kacmarcik, Travis Leithead 및 수년에 걸친 여러 기여자.

이 모델의 초판을 개척하는 데 도움을 주신 분들, 특히 다음 분들께 특별히 감사드린다: Charu Chandiram, Peter Freiling, Nathan Furtwangler, Thomas Olsen, Matt Rakow, Ramu Ramanathan, Justin Rogers, Jacob Rossi, Reed Townsend 및 Steve Wright.

B. 개정 이력

이 섹션은 비규범적이다.

다음은 [PointerEvents3] 명세와 비교한, 이 명세의 각 공개 버전 사이의 실질적이고 주요한 편집 변경 사항에 대한 정보 제공용 요약이다. 이 명세의 편집자 초안의 전체 개정 이력을 참조한다.

C. IDL 색인

WebIDLdictionary PointerEventInit : MouseEventInit {
    long        pointerId = 0;
    double      width = 1;
    double      height = 1;
    float       pressure = 0;
    float       tangentialPressure = 0;
    long        tiltX;
    long        tiltY;
    long        twist = 0;
    double      altitudeAngle;
    double      azimuthAngle;
    DOMString   pointerType = "";
    boolean     isPrimary = false;
    long        persistentDeviceId = 0;
    sequence<PointerEvent> coalescedEvents = [];
    sequence<PointerEvent> predictedEvents = [];
};

[Exposed=Window]
interface PointerEvent : MouseEvent {
    constructor(DOMString type, optional PointerEventInit eventInitDict = {});
    readonly        attribute long        pointerId;
    readonly        attribute double      width;
    readonly        attribute double      height;
    readonly        attribute float       pressure;
    readonly        attribute float       tangentialPressure;
    readonly        attribute long        tiltX;
    readonly        attribute long        tiltY;
    readonly        attribute long        twist;
    readonly        attribute double      altitudeAngle;
    readonly        attribute double      azimuthAngle;
    readonly        attribute DOMString   pointerType;
    readonly        attribute boolean     isPrimary;
    readonly        attribute long        persistentDeviceId;
    [SecureContext] sequence<PointerEvent> getCoalescedEvents();
    sequence<PointerEvent> getPredictedEvents();
};

partial interface Element {
  undefined setPointerCapture (long pointerId);
  undefined releasePointerCapture (long pointerId);
  boolean hasPointerCapture (long pointerId);
};

partial interface mixin GlobalEventHandlers {
    attribute EventHandler onpointerover;
    attribute EventHandler onpointerenter;
    attribute EventHandler onpointerdown;
    attribute EventHandler onpointermove;
    [SecureContext] attribute EventHandler onpointerrawupdate;
    attribute EventHandler onpointerup;
    attribute EventHandler onpointercancel;
    attribute EventHandler onpointerout;
    attribute EventHandler onpointerleave;
    attribute EventHandler ongotpointercapture;
    attribute EventHandler onlostpointercapture;
};

partial interface Navigator {
    readonly  attribute long maxTouchPoints;
};

dictionary MouseEventInit : EventModifierInit {
	long screenX = 0;
	long screenY = 0;
	long clientX = 0;
	long clientY = 0;

	short button = 0;
	unsigned short buttons = 0;
	EventTarget? relatedTarget = null;
};

[Exposed=Window]
interface MouseEvent : UIEvent {
	constructor(DOMString type, optional MouseEventInit eventInitDict = {});
	readonly attribute long screenX;
	readonly attribute long screenY;
	readonly attribute long clientX;
	readonly attribute long clientY;
	readonly attribute long layerX;
	readonly attribute long layerY;

	readonly attribute boolean ctrlKey;
	readonly attribute boolean shiftKey;
	readonly attribute boolean altKey;
	readonly attribute boolean metaKey;

	readonly attribute short button;
	readonly attribute unsigned short buttons;

	readonly attribute EventTarget? relatedTarget;

	boolean getModifierState(DOMString keyArg);
};

dictionary WheelEventInit : MouseEventInit {
    double deltaX = 0.0;
    double deltaY = 0.0;
    double deltaZ = 0.0;
    unsigned long deltaMode = 0;
    boolean momentum = false;
};

[Exposed=Window]
interface WheelEvent : MouseEvent {
    constructor(DOMString type, optional WheelEventInit eventInitDict = {});
    // DeltaModeCode
    const unsigned long DOM_DELTA_PIXEL = 0x00;
    const unsigned long DOM_DELTA_LINE	= 0x01;
    const unsigned long DOM_DELTA_PAGE	= 0x02;

    readonly attribute double deltaX;
    readonly attribute double deltaY;
    readonly attribute double deltaZ;
    readonly attribute unsigned long deltaMode;
    readonly attribute boolean momentum;
};

partial interface MouseEvent {
	// Deprecated in this specification
	undefined initMouseEvent(DOMString typeArg,
		optional boolean bubblesArg = false,
		optional boolean cancelableArg = false,
		optional Window? viewArg = null,
		optional long detailArg = 0,
		optional long screenXArg = 0,
		optional long screenYArg = 0,
		optional long clientXArg = 0,
		optional long clientYArg = 0,
		optional boolean ctrlKeyArg = false,
		optional boolean altKeyArg = false,
		optional boolean shiftKeyArg = false,
		optional boolean metaKeyArg = false,
		optional short buttonArg = 0,
		optional EventTarget? relatedTargetArg = null);
};

D. 참고 문헌

D.1 규범적 참고 문헌

[CSS-OVERFLOW-3]
CSS 오버플로 모듈 레벨 3. Elika Etemad; Florian Rivoal. W3C. 2025년 10월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/css-overflow-3/
[css-position]
CSS 위치 지정 레이아웃 모듈 레벨 3. Elika Etemad; Tab Atkins Jr. W3C. 2025년 10월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/css-position-3/
[CSS21]
종속형 스타일 시트 레벨 2 개정 1(CSS 2.1) 명세. Bert Bos; Tantek Çelik; Ian Hickson; Håkon Wium Lie. W3C. 2011년 6월 7일. W3C 권고안. URL: https://www.w3.org/TR/CSS2/
[CSSOM-View]
CSSOM View 모듈. Simon Fraser; Emilio Cobos Álvarez. W3C. 2025년 9월 16일. W3C 작업 초안. URL: https://www.w3.org/TR/cssom-view-1/
[DOM]
DOM 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세. Ecma International. URL: https://tc39.es/ecma262/multipage/
[HTML]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[HTML401]
HTML 4.01 명세. Dave Raggett; Arnaud Le Hors; Ian Jacobs. W3C. 2018년 3월 27일. W3C 권고안. URL: https://www.w3.org/TR/html401/
[infra]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[PointerLock]
Pointer Lock 2.0. Mustaq Ahmed; Vincent Scheib. W3C. 2026년 2월 25일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerlock-2/
[RFC2119]
요구사항 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc2119/
[RFC8174]
RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[TOUCH-EVENTS]
터치 이벤트. Doug Schepers; Sangwhan Moon; Matt Brubeck; Arthur Barstow. W3C. 2013년 10월 10일. W3C 권고안. URL: https://www.w3.org/TR/touch-events/
[UIEvents]
UI 이벤트. Xiaoqian Wu. W3C. 2026년 2월 21일. W3C 작업 초안. URL: https://www.w3.org/TR/uievents/
[UIEvents-Key]
UI Events KeyboardEvent key 값. Travis Leithead; Gary Kacmarcik. W3C. 2025년 4월 22일. W3C 권고안. URL: https://www.w3.org/TR/uievents-key/
[WEBDRIVER-BIDI]
WebDriver BiDi. James Graham; Alex Rudenko; Maksim Sadym. W3C. 2026년 9월 30일. W3C 작업 초안. URL: https://www.w3.org/TR/webdriver-bidi/
[WEBIDL]
Web IDL 표준. Edgar Chen; Timothy Gu. WHATWG. 현행 표준. URL: https://webidl.spec.whatwg.org/

D.2 정보 제공용 참고 문헌

[COMPAT]
호환성 표준. Mike Taylor. WHATWG. 현행 표준. URL: https://compat.spec.whatwg.org/
[PointerEvents]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 10월 5일. W3C 작업 초안. URL: https://www.w3.org/TR/pointerevents4/
[PointerEvents3]
포인터 이벤트. Patrick Lauke; Robert Flack. W3C. 2026년 6월 30일. W3C 권고안. URL: https://www.w3.org/TR/pointerevents3/
[WCAG22]
웹 콘텐츠 접근성 지침(WCAG) 2.2. Michael Cooper; Andrew Kirkpatrick; Alastair Campbell; Rachael Bradley Montgomery; Charles Adams. W3C. 2024년 12월 12일. W3C 권고안. URL: https://www.w3.org/TR/WCAG22/