>  기사  >  웹 프론트엔드  >  JavaScript로 제스처 라이브러리를 구현하는 방법

JavaScript로 제스처 라이브러리를 구현하는 방법

醉折花枝作酒筹
醉折花枝作酒筹앞으로
2021-05-07 09:25:322536검색

이 글에서는 JS에서 날짜 크기 비교를 구현하는 방법을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

JavaScript로 제스처 라이브러리를 구현하는 방법

Start 이벤트

먼저 손가락이 화면을 터치할 때 트리거되는 첫 번째 이벤트인 시작 이벤트를 트리거합니다. 이때 세 가지 상황이 발생합니다:

  • 손가락 풀기
    • tap클릭 동작을 구성하는 종료 이벤트를 트리거합니다
    • 종료 이벤트를 들으면서 알 수 있습니다
  • 손가락을 10픽셀 이상 드래그하세요
    • 이것은 pan start드래그 동작
    • 이동 이벤트에서 현재 접점과 이전 접점 사이의 거리를 판단할 수 있습니다
  • 손가락이 0.5초 이상 현재 위치에 유지됩니다
    • 이것은 press start를 누르는 동작입니다press start 按压的行为
    • 我们可以添加一个 setTimeout 来实现

Press 事件

所以我们第一步就是在 start 函数中加入一个 setTimout 的 handler 处理程序。

let handler;let start = point => {
  handler = setTimeout(() => {
    console.log('presss ');
  }, 500);};

一般来说 press 是我们比较常见的一个行为。但是实际上这里是 press start 事件,后面还会跟随着一个 press end 的事件。我们也可以统称这个为 press 事件,然后这个手势库的使用者只需要监听这个 press 事件即可,极少的情况下是需要监听 press end 事件的。

这里我们需要注意的是,当我们触发其他的事件的时候,这个 500 毫秒的 setTimout 是有可能会被取消掉的。所以我们需要给这段逻辑一个 handler,并且放在全局作用域中,让其他事件可以获取到这个变量,并且可使用它取消掉这个处理逻辑。

Pan 事件

接下来我们就去监听移动 10px 的 pan 事件,这里就需要我们记录一开始用户触摸屏幕时的 x 和 y 坐标,当用户移动手指的时候,持续计算新移动到的位置与初始位置的距离。如果这个距离超过了 10px 就可以触发我们的 pan start 的事件了。

所以首先我们需要在 start 函数中加入 startXstartY

setTimeout을 추가하여

Press 이벤트

isPan 的状态,第一次移动超出 10px 的时候,就会触发 pan-start 事件,并且把 isPan 置为 true,而后面的所有移动都会触发 pan 事件。

根据我们上面讲到的 press 事件,如果我们按下手指后 0.5 秒内出现了移动,那么 press 事件就会被取消。所以这里我们就需要 clearTimeoutpressstarthandler

따라서 첫 번째 단계는 startsetTimout을 추가하는 것입니다. > 함수 > 핸들러.

let handler;let startX, startY;let isPan = false;let start = point => {
  (startX = point.clientX), (startY = point.clientY);

  isPan = false;

  handler = setTimeout(() => {
    console.log('pressstart');
  }, 500);};let move = point => {
  let dx = point.clientX - startX,
    dy = point.clientY - startY;

  let d = dx ** 2 + dy ** 2;

  if (!isPan && d > 100) {
    isPan = true;
    console.log('pan-start');
    clearTimeout(handler);
  }

  if (isPan) {
    console.log(dx, dy);
    console.log('pan');
  }};

일반적으로 누르기는 우리에게 흔한 행동입니다. 그러나 실제로 이것은 프레스 시작 이벤트이고 이어서 프레스 종료 이벤트가 이어집니다. 또한 이를 press 이벤트라고 총칭할 수도 있으며, 이 제스처 라이브러리의 사용자는 이 press 이벤트를 수신하기만 하면 됩니다. 드문 경우지만 수신 대기가 필요합니다. 종료를 누르세요 이벤트.

여기서 주의해야 할 점은 다른 이벤트를 트리거할 때 이 500밀리초 setTimout이 취소될 수 있다는 것입니다. 따라서 우리는 이 로직에 handler를 제공하고 다른 이벤트가 이 변수를 획득하고 이를 사용하여 이 처리 로직을 취소할 수 있도록 전역 범위에 배치해야 합니다.

🎜팬 이벤트🎜🎜🎜🎜다음으로 가자 10px 이동하는 pan 이벤트 여기서는 사용자가 처음에 화면을 터치할 때 x 및 y 좌표를 기록해야 하며, 새로 이동한 손가락 사이의 거리를 계속 계산해야 합니다. 위치와 초기 위치. 이 거리가 10px를 초과하면 🎜 이벤트가 트리거될 수 있습니다. 🎜🎜먼저 시작 함수에 startXstartY의 좌표 레코드를 추가해야 합니다. 여기서 주목해야 할 점은 이 두 값이 다음과 같다는 것입니다. in 여러 위치에서 사용되므로 전역 범위에서도 선언해야 합니다. 🎜🎜이후 이동 기능에서 현재 접점과 시작점 사이의 직경 거리를 계산합니다. 여기서는 수학 z 2 x^2 + y^2 = z^2x의 직경 계산 공식을 사용해야 합니다. 2 +y 2 =z 2 , 여기서 x는 현재 접점의 x좌표 - 시작점의 x좌표 사이의 x축 거리이고, y는 현재 나가는 지점의 y좌표에서 계산된 y축 거리 - 시작점의 y좌표입니다. 2의 제곱으로 제곱된 두 거리의 최종 합은 2의 제곱으로 제곱된 직경 거리입니다. 🎜🎜 코드에서는 일반적으로 급진적인 연산을 사용하지 않으려고 합니다. 왜냐하면 급진적인 연산은 성능에 일정한 영향을 미치기 때문입니다. 우리가 궁극적으로 판단해야 할 것은 직경 거리가 고정된 10px보다 큰지 여부라는 것을 알고 있습니다. 즉, z = 10이고 z의 두 번째 거듭제곱이 100이므로 직경 거리가 100보다 큰지 직접 확인할 수 있습니다. 🎜🎜여기서 주목해야 할 또 다른 점은 손가락이 10px 이상 움직일 때 손가락이 화면을 떠나지 않고 뒤로 이동하면 더 이상 시작점에서 10px 떨어져 있지 않다는 것입니다. 하지만 이것은 실제로 팬 이벤트입니다. 왜냐하면 우리가 10px 이상의 거리를 이동했고 이 거리 이후의 모든 움직임은 팬 이벤트이기 때문입니다. 🎜🎜그래서 isPan 상태가 필요합니다. 첫 번째 움직임이 10px를 초과하면 pan-start 이벤트가 트리거되고 isPan가 true로 설정됩니다. , 이후의 모든 움직임은 pan 이벤트를 트리거합니다. 🎜🎜위에서 언급한 누르기 이벤트에 따라 손가락을 누른 후 0.5초 이내에 움직임이 있으면 누르기 이벤트가 취소됩니다. 따라서 여기서 pressstarthandler를 지우려면 clearTimeout이 필요합니다. 🎜
let handler;let startX, startY;let isPan = false,
  isPress = false,
  isTap = false;let start = point => {
  (startX = point.clientX), (startY = point.clientY);

  isPan = false;
  isTap = true;
  isPress = false;

  handler = setTimeout(() => {
    isPan = false;
    isTap = false;
    isPress = true;
    console.log('press-start');
    handler = null;
  }, 500);};let move = point => {
  let dx = point.clientX - startX,
    dy = point.clientY - startY;

  let d = dx ** 2 + dy ** 2;

  if (!isPan && d > 100) {
    isPan = true;
    isTap = false;
    isPress = false;
    console.log('pan-start');
    clearTimeout(handler);
  }

  if (isPan) {
    console.log(dx, dy);
    console.log('pan');
  }};let end = point => {
  if (isTap) {
    console.log('tap');
    clearTimeout(handler);
  }};
🎜탭이벤트🎜🎜🎜🎜

Tap 的这个逻辑我们可以在 end 事件里面去检查。首先我们默认有一个 isTap 等于 true 的状态,如果我们触发了 pan 事件的话,那就不会去触发 tap 的逻辑了,所以 tap 和 pan 是互斥的关系。但是为了不让它们变得很耦合,所以我们不使用原有的 isPan 作为判断状态,而是另外声明一个 isTap 的状态来记录。

这里我们 tap 和 pan 都有单独的状态,那么我们 press 也不例外,所以也给 press 加上一个 isPress 的状态,它的默认值是 false。如果我们 0.5 秒的定时器被触发了,isPress 也就会变成 true。

既然我们给每个事件都加入了状态,那么这里我们就给每一个事件触发的时候设置好这些状态的值。

  • press 时  
    • isTap = false
    • isPan = false
    • isPress = true
  • pan 时  
    • isTap = false
    • isPan = true
    • isPress = false
  • tap 时  
    • isTap = true
    • isPan = false
    • isPress = false

如果我们发现用户没有移动,也没有按住触屏超过 0.5 秒,当用户离开屏幕时就会调用 end 函数,这个时候我们就可以认定用户的操作就是 tap。这里我们要注意的是,我们 press 的 0.5 秒定时器是没有被关闭的,所以我们在 isTap 的逻辑中需要 clearTimeout(handler)

说到取消 press 定时器,其实我们 handler 的回调函数中,也需要做一个保护代码逻辑,在触发了 press-start 之后,我们需要保证每次点击屏幕只会触发一次,所以在 setTimout 的回调函数中的最后,我们需要加上 handler = null。这样只要 press-start 触发了,就不会再被触发。

let handler;let startX, startY;let isPan = false,
  isPress = false,
  isTap = false;let start = point => {
  (startX = point.clientX), (startY = point.clientY);

  isPan = false;
  isTap = true;
  isPress = false;

  handler = setTimeout(() => {
    isPan = false;
    isTap = false;
    isPress = true;
    console.log('press-start');
    handler = null;
  }, 500);};let move = point => {
  let dx = point.clientX - startX,
    dy = point.clientY - startY;

  let d = dx ** 2 + dy ** 2;

  if (!isPan && d > 100) {
    isPan = true;
    isTap = false;
    isPress = false;
    console.log('pan-start');
    clearTimeout(handler);
  }

  if (isPan) {
    console.log(dx, dy);
    console.log('pan');
  }};let end = point => {
  if (isTap) {
    console.log('tap');
    clearTimeout(handler);
  }};

End 事件

到了最后这里我们要处理的就是所有的结束时间,包括 press-endpan-end

这两个 end 事件都会在 end 函数中判断所得,如果在用户操作的过程中触发了 pan-start 或者 press-start 事件,到了 end 函数这里,对应的状态就会是 true。

所以我们对 end 函数做了以下改造:

let end = point => {
  if (isTap) {
    console.log('tap');
    clearTimeout(handler);
  }

  if (isPan) {
    console.log('pan-end');
  }

  if (isPress) {
    console.log('press-end');
  }};

最后我们需要在 cancel 事件触发的时候,清楚掉 press 事件的 setTimeout。既然我们的操作被打断了,那也不可能会触发我们的长按事件了。

// 加入 cancellet cancel = point => {
  clearTimeout(handler);
  console.log('cancel');};

我们除了 flick 的逻辑,我们已经完成所有手势库里面的事件了。并且也能正确的区分这几种手势操作了。

【推荐学习:javascript高级教程

위 내용은 JavaScript로 제스처 라이브러리를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제