포인터 이벤트 (step 26)

KHW·2021년 2월 8일
0

js-study

목록 보기
8/39
post-custom-banner

이전 내용

기본적으로 브라우저에는 drag와 관련한 드래그 앤 드롭을 지원이 지원하는 곳이 있다. 이를 내가 원하는 코드와 충돌하지않게 하기 위해서는

    Dom.ondragstart = function() {
      return false;
    };

이러한 내용을 추가해주어야 한다.


포인트 이벤트

다양한 터치 장치들이 증가하면서 필요성이 요구된 내용들
ex) 멀티터치


포인트 이벤트 유형

포인터 이벤트유사한 마우스 이벤트
pointerdownmousedown
pointerupmouseup
pointermovemousemove
pointerovermouseover
pointeroutmouseout
pointerentermouseenter
pointerleavemouseleave
pointercancel-
gotpointercapture-
lostpointercapture

포인터 이벤트 속성

  1. pointerId – 이벤트를 유발하는 포인터의 고유 식별자.
    브라우저 생성. 스타일러스 및 멀티 터치가있는 터치 스크린과 같은 여러 포인터를 처리 할 수 ​​있습니다 (예는 다음과 같습니다).
  2. pointerType– "마우스", "펜"또는 "터치"중 하나의 문자열
    이 속성을 사용하여 다양한 포인터 유형에 대해 다르게 반응 할 수 있습니다.
  3. isPrimary– true기본 포인터 용입니다 (멀티 터치의 첫 번째 손가락).
    document.onpointerdown = document.onpointerup = log;

    function log(event) {
      area.insertAdjacentHTML("beforeend", `
        <div>${event.type} isPrimary=${event.isPrimary} pointerId=${event.pointerId}   ==   ${event.pointerType}</div>
      `)
     area.scrollTop = 1e9;
    }

예를들어
pointerId는 고유 식별자로 마우스로 클릭하는것은 같은 Id이나 폰으로 터치는 각각 다른 Id로 인식한다.
isPrimary은 기존에 폰으로 어떤 지점을 누루고 있는 상태에서 다른 멀티 터치들은 전부 false이고 처음 멀티터치의 부분만 true인 상태다.
마우스로 클릭을 진행한다면 pointerTypemouse 결과고 폰으로 클릭할 경우 touch라고 결과가 뜬다.

  1. width– 포인터 (예 : 손가락)가 장치에 닿는 영역의 너비. 지원되지 않는 경우 (예 : 마우스) 항상 1.
  2. height– 포인터가 장치에 닿는 영역의 높이. 지원되지 않는 경우 항상 1.
  3. pressure– 포인터 팁의 압력 범위는 0에서 1 사이입니다. 압력을 지원하지 않는 장치의 경우 0.5(눌려 짐) 또는 0.
 <strong>${event.width}==${event.height}==${event.pressure}</strong>

코드 추가

휴대폰에서 실행시 누를때 pressure는 1 뗄때는 0을 나타내고 그 외의 width height도 나타난다.

이벤트 : 포인터 취소

이번에도 저번내용 처럼 마찬가지로 의도한 코드를 정상적으로 실행하기 위해서 드래그 앤 드롭을 지원이 지원하는 곳과 충돌을 피하기 위해

ball.ondragstart = () => false; 내용을 추가해준다.


포인터 캡쳐

문서에서 실제로 발생한 위치에 관계없이 대상 (에서 발생한 것처럼)을 pointerId갖는것

<!DOCTYPE html>
<html lang="en-US">

<body>
<button onpointerdown="pointDown(event)" onpointerup="pointerUp(event);">Press Me</button>
<p id="point"></p>

<script>
var x = document.getElementById("point");
var elem = document.getElementsByTagName("button")[0];

function pointDown(e){
 elem.setPointerCapture(e.pointerId);
 check(e);
}

function pointerUp(e){
 elem.releasePointerCapture(e.pointerId);
 check(e);
}

function check(e){ 
 if(elem.hasPointerCapture(e.pointerId))
   x.innerHTML = "Your mouse pointer is captured";
 else
   x.innerHTML = "Your mouse pointer is released";
}
</script>
  </body>
</html>

버튼을 누른상태면 button 객체인 elem이 e.pointerId 설정이 되어 elem.hasPointerCapture(e.pointerId)true를 반환하고
버튼을 띄게 되면 button 객체인 elem이 e.pointerId 설정이 되어 elem.hasPointerCapture(e.pointerId)false를 반환한다.

코드 수정본

<!DOCTYPE html>
<html lang="en-US">

<body>
<button onpointerdown="pointDown(event)" onpointerup="pointerUp(event);" >Press Me</button>
<button onpointerdown="pointDown(event)" onpointerup="pointerUp(event);" >Press not me</button>
<p id="point"></p>

<script>
var x = document.getElementById("point");
var elem = document.getElementsByTagName("button")[0];
var elem1 = document.getElementsByTagName("button")[1];

function pointDown(e){
 elem.setPointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
  elem1.setPointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
}

function pointerUp(e){
 elem.releasePointerCapture(e.pointerId);
  console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
   elem1.releasePointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
}

</script>
  </body>
</html>

function pointDown(e){
 elem.setPointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
  elem1.setPointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
}

이를 실행해보면 첫번째 버튼을 클릭할경우 true false 결과와 false true 결과가 나타나는데 이는 우리가 첫번째버튼을 누르면서 생긴 e.pointerId elem.setPointerCapture(e.pointerId);에 의해 capture했다가 elem1.setPointerCapture(e.pointerId);에 의해 capture가 바뀌어 false true로 결과가 나타난다.


function pointerUp(e){
 elem.releasePointerCapture(e.pointerId);
  console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
   elem1.releasePointerCapture(e.pointerId);
   console.log(elem.hasPointerCapture(e.pointerId),elem1.hasPointerCapture(e.pointerId) )
}

버튼을 클릭하고 뗀 경우 elem.releasePointerCapture(e.pointerId);는 어차피 elem.hasPointerCapture(e.pointerId)이 false이므로 영향이 없고 elem1.releasePointerCapture(e.pointerId);에 의해서 Capture가 해제되므로 마지막 콘솔 결과가 false false로 나온다.


정리 : Dom.setPointerCapture(event.pointerId)Dom.releasePointerCapture(event.pointerId)에 의해서 이벤트가 발생한 곳을 캡쳐하여 다른 Dom에 설정시키거나 해제 할 수 있고 해당 다른 Dom은 이것이 적용되었는지 elem.hasPointerCapture(e.pointerId)를 통해서 확인 할 수 있다.


마지막 setPointerCapture정리

예제

<script>
  let thumb = slider.querySelector('.thumb');
  let shiftX;
let li2 = document.createElement('li');

  thumb.onpointerdown = function(event) {
    event.preventDefault(); // prevent selection start (browser action)
    shiftX = event.clientX - thumb.getBoundingClientRect().left;
    // retarget all pointer events (until pointerup) to thumb
    thumb.setPointerCapture(event.pointerId); // (*)
  };

  thumb.onpointermove = function(event) {
    // moving the slider: listen on the thumb, 
    // as all pointer events are retargeted to it
    let newLeft = event.clientX - shiftX - slider.getBoundingClientRect().left; // (*)

    // if the pointer is out of slider => adjust left to be within the bounaries
    if (newLeft < 0) {
      newLeft = 0;
    }
    let rightEdge = slider.offsetWidth - thumb.offsetWidth;
    if (newLeft > rightEdge) {
      newLeft = rightEdge;
    }

    thumb.style.left = newLeft + 'px';
  };

thumb.onpointerup = function(event){
 thumb.releasePointerCapture(event.pointerId); // (*)
}


</script>

thumb.setPointerCapture(event.pointerId); // (*) 이 부분이 없을 경우 우리는 마우스를 누른 상태에서 드래그를 하는 것이 불가능하다.
단지 마우스를 가져다 댄 채로 조금씩의 움직임이 가능하지(onpointermove)
하지만 thumb.setPointerCapture(event.pointerId); // (*) 내용이 있을 경우에는 마우스를 누른 상태에서 드래그 하는 것이 가능하다.

기본적으로 클릭 후 진행되는 mousemove와는 클릭과 관계가 적고 닿으면 반응하는 pointermove는 클릭 후 떼기 전까지 poinermove를 진행하려면 setPoinerCapture로 해당 event를 잡은 상태로 진행해야 되므로 따라서 위와같이 코드가 작성되어야 한다.
(poinerdown안에 setPointerCapture가 들어가 있고 pointermove가 따로 존재하고 pointerup으로 끝이나면 releasePointerCapture 진행

=>위의 의견은 개인적인 의견


중요 부분 정리

Dom.setPointerCapture(event.pointerId) 로 사용한다.
브라우저에서 기본적으로 작동하는 이벤트 들이 코드의 이벤트와 충돌하지않게 주의
mouse이벤트와 pointer이벤트는 비슷하면서도 다르다. (move 부분에서의 마우스 클릭시와 포인터는 닿는것의 영향)
(mouse는 누르고 움직여야 move이지만 , pointer는 누르는것없이 드래그로도 move의 역할을 수행한다.)

출처

포인트 이벤트
포인터 캡쳐

profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자
post-custom-banner

2개의 댓글

comment-user-thumbnail
2021년 2월 11일

pointerType– 포인팅 장치 유형. "마우스", "펜"또는 "터치" 의 문자열이 그대로 번역이 되었네요

pointerType은 기존에 폰으로 어떤 지점을 누루고 있는 상태에서 다른 멀티 터치들은 전부 false이고 처음 멀티터치의 부분만 true인 상태다. pointerType → isPrimary` 로 번역 되어야 할 것 같습니다.

휴대폰에서도 width, height pressure 를 테스트 해본 결과가 인상깊네요

1개의 답글