npm i -S any-touch
<script src="https://unpkg.com/any-touch/dist/any-touch.umd.min.js"></script>
<script>
console.log(AnyTouch.version); // 2.x.x
</script>
import AnyTouch from 'any-touch';
const el = document.getElementById('box');
const at = new AnyTouch(el);
// e包含位移/速度/方向等信息
at.on('pan', (e) => console.log(e));
默认所有手势都会触发原生DOM事件, 所以在vue中可在模版元素上直接使用"@tap"等语法监听手势事件.
<template>
<div
@tap="onTap"
@swipe="onSwipe"
@press="onPress"
@pan="onPan"
@pinch="onPinch"
@rotate="onRotate">
<p>Hello any-touch</p>
</div>
</template>
<script>
import AnyTouch from 'any-touch';
export default {
mounted() {
// 没错, 就这2行
const at = new AnyTouch(this.$el);
this.$on('hook:destroyed', () => {
at.destroy();
});
},
};
</script>
注意: vue中 "@tap"这种语法只能用在元素标签上, 而不能用在自定义组件标签上:
<!-- 有效 -->
<div @tap="onTap"></div>
<!-- 不生效, 监听不到tap -->
<my-component @tap="onTap"></my-component>
由于小程序中没有 dom 元素的概念, 所以我们需要通过catchEvent方法手动接收touch事件的事件对象来进行识别
<view
@touchstart="at.catchEvent"
@touchmove="at.catchEvent"
@touchend="at.catchEvent"
@touchcancel="at.catchEvent">
</view>
const at = new AnyTouch()
{
onload(){
at.on('press', onPress);
}
}
默认 any-touch 支持所有手势, 为了更小的体积, 提供了按需加载.
// 只加载pan识别器(拖拽)
import AT from 'any-touch';
const at = AT(el);
at.on('tap', (e) => {});
at.on('pan', (e) => {});
// 同时监听多个事件
at.on(['swipe', 'press', 'rotate', 'pinch'], (e) => {});
安装"any-touch"时, 对应的"@any-touch/xxx"会自动安装, 直接引入即可.
// 只加载pan识别器(拖拽)
import Core from '@any-touch/core';
import pan from '@any-touch/pan
// Core不识别任何手势.
const at = new Core(el);
// 加载pan
at.use(pan);
at.on('pan', e=>{});
手势库的核心组件, 主要用来实现 PC/移动端的兼容(查看更多).
手势识别器均已做成独立的包, 从而实现按需加载.
名称 | 说明 |
---|---|
@any-touch/tap | 点击 |
@any-touch/pan | 拖拽 |
@any-touch/swipe | 划 |
@any-touch/press | 按压 |
@any-touch/pinch | 缩放 |
@any-touch/rotate | 旋转 |
识别器 | 事件名 | 说明 |
---|---|---|
tap | tap | 单击 |
press | press / pressup | 按压 / 松开 |
pan | pan / panstart / panmove / panend /panup/pandown/panright/panleft | 拖拽 / 拖拽开始 / 拖拽进行中 / 拖拽结束/ 上下左右滑动 |
swipe | swipe / swipeup / swipedown / swiperight / swipeleft | 快划 / 不同方向快划 |
pinch | pinch / pinchstart / pinchmove / pinchend / pinchin /pinchout | 缩放 / 缩放开始 / 缩放进行中 / 缩放结束 / 放大 / 缩小 |
rotate | rotate / rotatestart / rotatemove / rotateend | 旋转 / 旋转开始 / 旋转进行中 / 旋转结束 |
// 拖拽中只出发一次
at.on('panstart', (e) => {
console.log('拖拽开始');
});
参数"preventDefault"是一个函数, 可以通过他的返回值的"true/false"来决定是否"阻止默认事件".
比如实现: 阻止多点触发的事件的"默认事件", 比如"pinch/rotate".
const at = new AnyTouch(el, {
preventDefault(e) {
return 1 == e.touches.length;
},
});
参数"e"是原生事件对象, 移动端是TouchEvent, PC端是MouseEvent.
针对自定义的手势, 比如上面的"双击", 在ts中我们需要进行"类型扩充声明", 声明文件如下:
// global.d.ts
import tap from '@any-touch/tap';
declare module '@any-touch/core' {
// 扩充at.get('doubletap')返回值的类型
// 如不扩充, get返回的插件实例类型不完整.
export interface PluginContextMap {
doubletap: ReturnType<typeof tap>;
}
// 扩充at.on('doubletap',e=>{})中的e的类型
export interface EventMap {
doubletap: AnyTouchEvent;
}
}
当然不写声明文件也可以, 偷懒的方法是:
// ⭐让"e"和tap事件的e的类型一致,
// 毕竟都是tap识别器衍生的事件
at.on('doubletap' as 'tap', e=>{});
// ⭐返回tap识别器的实例,
// 其实就是同一个识别器的实例
at.get('doubletap' as 'tap');
注意: 上面2种写法都ok, 在这里写声明文件和断言其实没区别, 都可以正确的推导出其他部分的类型. 🚀 返回目录
宽泛的事件钩子.
名称 | 说明 |
---|---|
at:start | 开始触碰/触点增加触发 |
at:move | 触点移动触发 |
at:end | 触点离开触发 |
at:after | 任意事件触发后,其都会被触发 |
"at:after"的事件对象和其他事件的不同, 多一个name字段, 这个name表示哪个事件引起的"at:after".
at.on('at:after',e=>{
// ⭐tap/pan/swipe/press/pinch/rotate/at:start/at:move/at:end
console.log(e.name)
});
自定义手势一定记得给起一个名字哦, 而且不要和默认存在的手势同名(已有 tap/swipe/pan/rotate/pinch/press).
at.use(tap, { pointLength: 2, name: 'twoFingersTap' });
at.on('twoFingersTap', onTwoFingersTap);
❗❗❗ 在安卓手机的真机上, 如果touchstart
或touchmove
阶段触发了alert
, 会出现后续的touchmove/touchend
不触发的 bug. 所以请大家务必避免在手势的事件回调中使用alert
.
测试代码
如果仅仅是了在移动端调试, 请使用腾讯的vconsole
由于上述原因, swipe 事件发生的会"慢半拍",所以请大家最终测试以手机效果为准.
在移动端 touchstart 比 click 先触发, 所以 touchstart 阶段的 preventDefault 会阻止 click 触发, 恰恰 any-touch 默认在 touchstart 中使用了preventDefault
, 用来阻止了浏览器默认事件的触发,比如 click 和页面滚动.
如果移动端非要使用 click 做如下设置
const at = new AnyTouch(el, { preventDefault: false });
这是因为pnpm不像yarn和npm, 其不会把any-touch依赖的包安装到node_modules目录的根, 所以会提示找不到. 参考pnpm说明.
如果使用pnpm, 那么只能通过手动安装包解决.
pnpm i @any-touch/core @any-touch/tap @any-touch/press @any-touch/pan @any-touch/swipe @any-touch/pinch @any-touch/rotate