关键词:
前端组件化系列目录
- 「一」用 JSX 建立组件 Parser(解析器)
- 「二」使用 JSX 建立 Markup 组件风格
- 「三」用 JSX 实现 Carousel 轮播组件
- 「四」用 JavaScript 实现时间轴与动画
- 「五」用 JavaScript 实现手势库 - 实现监听逻辑
- 「六」用 JavaScript 实现手势库 — 手势逻辑 《 本期 》
- … 待续 …
上一期《实现监听逻辑》中我们一起实现了基础的手势监听逻辑。有了这些手势的监听后,我们就可以开始实现每一个手势的逻辑。最终我们可以把这些手势应用到我们的《轮播图组件》当中。
接下来我们就开始实现 gesture 的逻辑。
Start 事件
首先我们会触发一个 start 事件,也就是当我们手指触摸到屏幕时第一个触发的事件。这时会有三种情况:
- 手指松开
- 会触发 end 事件,这样就构成一个
tap
点击的行为 - 通过监听 end 事件来实现即可
- 会触发 end 事件,这样就构成一个
- 手指拖动超过 10 px
- 这种就是
pan start
拖动的行为 - 我们可以在 move 事件判断当前与上一个触点的距离
- 这种就是
- 手指停留在当前位置超过 0.5s
- 这种就是
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 函数中加入 startX
和 startY
的坐标记录,这里要注意的是,因为这两个值都是会在多个地方被使用的,所以也是需要在全局作用域中声明。
然后在 move
函数中计算当前触点与起点的直径距离。这里我们需要用到数学中的直径运算公式
x
2
+
y
2
=
z
2
x^2 + y^2 = z^2
x2+y2=z2,而这里面的 x 是 当前触点的 x 坐标
- 起点的 x 坐标
的 x 轴的距离, y 就是 当前出点的 y 坐标
- 起点的 y 坐标
运算出来的 y 轴的距离。最终两个距离二次幂相加就是直径距离的二次幂。
在代码中我们一般都会尽量避免使用根号运算,因为根号运算会对性能有一定的影响。我们知道最终要判断的是直径距离是否是大于一个固定的 10px。那就是说 z = 10,而 z 的二次幂就是 100,所以我们直接判断这个直径距离是否大于 100 即可。
这里还有一个需要注意的,就是当我们手指移动超过 10px 之后,如果我们手指没有离开屏幕而是往回移动了,这样的话我们距离起点已经不够 10px了。但是这个其实也是算 pan 事件,因为我们确实有移动超过 10px 距离,超过这个距离之后所有的移动都是属于 pan 事件。
所以我们需要一个 isPan
的状态,第一次移动超出 10px 的时候,就会触发 pan-start
事件,并且把 isPan
置为 true,而后面的所有移动都会触发 pan
事件。
根据我们上面讲到的 press
事件,如果我们按下手指后 0.5 秒内出现了移动,那么 press
事件就会被取消。所以这里我们就需要 clearTimeout
把 pressstart
的 handler
给清楚掉。
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');
;
Tap 事件
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-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。既然我们的操作被打断了,那也不可能会触发我们的长按事件了。
// 加入 cancel
let cancel = point =>
clearTimeout(handler);
console.log('cancel');
;
我们除了
flick
的逻辑,我们已经完成所有手势库里面的事件了。并且也能正确的区分这几种手势操作了。
这期我们就先到这里啦,下期我们就来一起完整这个手势库的逻辑,并且重新整理一次这里面的状态!~ 敬请期待,记得持续关注三哥哦~
我是来自《技术银河》的三钻,一位正在重塑知识的技术人。下期再见。
⭐️ 三哥推荐
开源项目推荐
Hexo Theme Aurora
在最近更新到版本 1.5.0,包含以下内容:
》预览《
✨ 新增
- 自适应 “推荐文章” 布局 (增加了一个新的 “
置顶文章布局
” !!)- 能够在“推荐文章”和“置顶文章”模式之间自由切换
- 如果总文章少于 3 篇,将自动切换到“置顶文章”模式
- 在文章卡上添加了“置顶”和“推荐”标签
- 📖 文档
- 增加了与 VuePress 一样的自定义容器 #77
Info
容器Warning
容器Danger
容器Detail
容器- 预览
- 支持了更多的 SEO meta 数据 #76
- 添加了
description
- 添加了
keywords
- 添加了
author
- 📖 文档
- 添加了
最近博主在全面投入开发一个可以 “迈向未来的” Hexo 主题,以极光为主题的博客主题。
如果你是一个开发者,做一个个人博客也是你简历上的一个亮光点。而如果你有一个超级炫酷的博客,那就更加是亮上加亮了,简直就闪闪发光。
如果喜欢这个主题,可以在 Github 上给我点个 🌟 让彼此都发光吧~
主题 Github 地址:https://github.com/auroral-ui/hexo-theme-aurora
主题使用文档:https://aurora.tridiamond.tech/zh/
VSCode Aurora Future
对,博主还做了一个 Aurora 的 VSCode 主题。用了Hexo Theme Aurora 相对应的颜色色系。这个主题的重点特性的就只用了 3 个颜色,减少在写代码的时候被多色多彩的颜色所转移了你的注意力,让你更集中在写代码之中。
喜欢的大家可以支持一下哦! 直接在 VSCode 的插件搜索中输入 “Aurora Future” 即可找到这个主题哦!~
主题 Github 地址:https://github.com/auroral-ui/aurora-future-vscode-theme
主题插件地址:https://marketplace.visualstudio.com/items?itemName=auroral-ui.aurora-future
Firefox Aurora Future
我不知道大家,但是最近我在用火狐浏览器来做开发了。个人觉得火狐还真的是不错的。推荐大家尝试一下。
当然我这里想给大家介绍的是我在火狐也做了一个 Aurora 主题。对的!用的是同一套的颜色体系。喜欢的小伙伴可以试一下哦!
主题地址:https://addons.mozilla.org/en-US/firefox/addon/aurora-future/
用javascript实现手势库—封装手势库前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—手势动画应用前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—手势动画应用前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—手势动画应用前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—手势动画应用前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—支持多键触发前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—事件派发与flick事件前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—事件派发与flick事件前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库—事件派发与flick事件前端组件化(代码片段)
...立Markup组件风格「三」用JSX实现Carousel轮播组件「四」用JavaScript实现时间轴与动画「五」用JavaScript实现三次贝塞尔动画库-前端组件化「六」用JavaScript实现手势库-实现监听逻辑「七」用JavaScript实现手势库—手势逻辑「八」用Java... 查看详情
用javascript实现手势库-实现监听逻辑前端组件化(代码片段)
在之前的文章中我们一起实现了一个轮播图的基本效果,我们可以用鼠标去把它来回拖拽。效果上它已经是一个可以做到无尽轮播的轮播图功能了。但是我们会发现,我们鼠标在图片上任何的动作都会触发到拖拽,并... 查看详情
实现一个javascript手势库--base-gesture.js
...这些东西就感觉网页会库不少呢~~(舒服)。当然啦。原生javascript并没有为我们提供这些花里胡哨的东西,需要我们自己去实现下喽。又当然,,现在还是有许多js手势库的,比如hammer.js 查看详情
用javascript实现时间轴与动画-前端组件化(代码片段)
上一篇文章《用JSX实现Carousel轮播组件》中,我们实现了一个“基础”的轮播组件。为什么我们叫它“基础”呢?因为其实它看起来已经可以满足我们轮播组件的功能,但是其实它还有很多缺陷我们是没有去完善的。... 查看详情
h5移动端手势密码组件
...移动端开发的技术啦~~ 本项目采用原生JS和Canvas实现移动端手势密码组件,支持手势密码设置和验证。 先加星后看,年薪百万!欢迎大家关注我的github,互相学习~~ & 查看详情
使用rollup打包一个原生js+canvas实现的移动端手势解锁功能组件
...开屏幕时,判定为密码输入正确,否则密码错误。要求:实现一个移动网页,允许用户设置手势密码和验证手势密码。已设置的密码记录在本地localStorage中。stat1:设置密码。用户选择设置密码时,要提示用户输入手势密码。stat... 查看详情
flutter(五)手势gesturedetector
...除了少部分组件,如Button相关的组件可以直接通过onPressed实现点击事件。其余组件想实现点击、长按等事件,都需要借助GestureDetector来实现手势监听下面介绍比较常用的手势如onTap(点击)、onDoubleTap(双击)、onLongPress(长按)... 查看详情
使用rollup打包一个原生js+canvas实现的移动端手势解锁功能组件(代码片段)
说明2017前端星计划选拔作业学习笔记源码笔记:https://github.com/kaimo313/h5-handlelock原型和操作流程用户用手指按顺序依次划过9个原点中的若干个(必须不少于4个点),如果划过的点的数量和顺序与之前用户设置的... 查看详情
仅对 touchesBegan 和 NOT 手势识别器使用 hitTest 逻辑
...旋转以及其他手势识别器。拖拽是通过touchesBegan/Moved/Ended实现的,旋转是通过识别器实现的。视图 查看详情
xamarin.forms第23局:手势识别
...:处理用户点击(单击或双击)操作,用TapGestureRecognizer类实现。1.GestureRecognizers:所有视图元素都有此手势识别集合集合。向这个集合添加手势使元素获得响应用户手势的功能。2.TapGestureRecognizer主要属性及事件:缩放手势(捏合手... 查看详情