이 글에서는 JS에서 날짜 크기 비교를 구현하는 방법을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
먼저 손가락이 화면을 터치할 때 트리거되는 첫 번째 이벤트인 시작 이벤트를 트리거합니다. 이때 세 가지 상황이 발생합니다:
tap
클릭 동작을 구성하는 종료 이벤트를 트리거합니다pan start
드래그 동작press start
를 누르는 동작입니다press start
按压的行为所以我们第一步就是在 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
,并且放在全局作用域中,让其他事件可以获取到这个变量,并且可使用它取消掉这个处理逻辑。
接下来我们就去监听移动 10px 的 pan
事件,这里就需要我们记录一开始用户触摸屏幕时的 x 和 y 坐标,当用户移动手指的时候,持续计算新移动到的位置与初始位置的距离。如果这个距离超过了 10px 就可以触发我们的 pan start
的事件了。
所以首先我们需要在 start 函数中加入 startX
和 startY
Press 이벤트
isPan
的状态,第一次移动超出 10px 的时候,就会触发 pan-start
事件,并且把 isPan
置为 true,而后面的所有移动都会触发 pan
事件。
根据我们上面讲到的 press
事件,如果我们按下手指后 0.5 秒内出现了移动,那么 press
事件就会被取消。所以这里我们就需要 clearTimeout
把 pressstart
的 handler
start
에 setTimout
을 추가하는 것입니다. > 함수 > 핸들러. 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
를 제공하고 다른 이벤트가 이 변수를 획득하고 이를 사용하여 이 처리 로직을 취소할 수 있도록 전역 범위에 배치해야 합니다.
pan
이벤트 여기서는 사용자가 처음에 화면을 터치할 때 x 및 y 좌표를 기록해야 하며, 새로 이동한 손가락 사이의 거리를 계속 계산해야 합니다. 위치와 초기 위치. 이 거리가 10px를 초과하면 🎜 이벤트가 트리거될 수 있습니다. 🎜🎜먼저 시작 함수에 startX
및 startY
의 좌표 레코드를 추가해야 합니다. 여기서 주목해야 할 점은 이 두 값이 다음과 같다는 것입니다. 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초 이내에 움직임이 있으면 누르기
이벤트가 취소됩니다. 따라서 여기서 pressstart
의 handler
를 지우려면 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。
既然我们给每个事件都加入了状态,那么这里我们就给每一个事件触发的时候设置好这些状态的值。
如果我们发现用户没有移动,也没有按住触屏超过 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); }};
到了最后这里我们要处理的就是所有的结束时间,包括 press-end
和 pan-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 중국어 웹사이트의 기타 관련 기사를 참조하세요!